Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Unified Diff: pkg/analyzer/lib/src/generated/utilities_collection.dart

Issue 198453002: New analyzer snapshot. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « pkg/analyzer/lib/src/generated/resolver.dart ('k') | pkg/analyzer/test/generated/ast_test.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/analyzer/lib/src/generated/utilities_collection.dart
diff --git a/pkg/analyzer/lib/src/generated/utilities_collection.dart b/pkg/analyzer/lib/src/generated/utilities_collection.dart
index ef713f706a3924a3658c5162c958957b93dbca9d..b8b789097ed2441731ef63bcdff62869fbdfe79a 100644
--- a/pkg/analyzer/lib/src/generated/utilities_collection.dart
+++ b/pkg/analyzer/lib/src/generated/utilities_collection.dart
@@ -112,6 +112,333 @@ class TokenMap {
}
/**
+ * Instances of the class `DirectedGraph` implement a directed graph in which the nodes are
+ * arbitrary (client provided) objects and edges are represented implicitly. The graph will allow an
+ * edge from any node to any other node, including itself, but will not represent multiple edges
+ * between the same pair of nodes.
+ *
+ * @param N the type of the nodes in the graph
+ */
+class DirectedGraph<N> {
+ /**
+ * The table encoding the edges in the graph. An edge is represented by an entry mapping the head
+ * to a set of tails. Nodes that are not the head of any edge are represented by an entry mapping
+ * the node to an empty set of tails.
+ */
+ Map<N, Set<N>> _edges = new Map<N, Set<N>>();
+
+ /**
+ * Add an edge from the given head node to the given tail node. Both nodes will be a part of the
+ * graph after this method is invoked, whether or not they were before.
+ *
+ * @param head the node at the head of the edge
+ * @param tail the node at the tail of the edge
+ */
+ void addEdge(N head, N tail) {
+ //
+ // First, ensure that the tail is a node known to the graph.
+ //
+ if (_edges[tail] == null) {
+ _edges[tail] = new Set<N>();
+ }
+ //
+ // Then create the edge.
+ //
+ Set<N> tails = _edges[head];
+ if (tails == null) {
+ tails = new Set<N>();
+ _edges[head] = tails;
+ }
+ tails.add(tail);
+ }
+
+ /**
+ * Add the given node to the set of nodes in the graph.
+ *
+ * @param node the node to be added
+ */
+ void addNode(N node) {
+ Set<N> tails = _edges[node];
+ if (tails == null) {
+ _edges[node] = new Set<N>();
+ }
+ }
+
+ /**
+ * Return a list of nodes that form a cycle, or `null` if there are no cycles in this graph.
+ *
+ * @return a list of nodes that form a cycle
+ */
+ List<N> findCycle() => null;
+
+ /**
+ * Return a list of nodes that form a cycle containing the given node. If the node is not part of
+ * this graph, then a list containing only the node itself will be returned.
+ *
+ * @return a list of nodes that form a cycle containing the given node
+ */
+ List<N> findCycleContaining(N node) {
+ if (node == null) {
+ throw new IllegalArgumentException();
+ }
+ DirectedGraph_SccFinder<N> finder = new DirectedGraph_SccFinder<N>(this);
+ return finder.componentContaining(node);
+ }
+
+ /**
+ * Return the number of nodes in this graph.
+ *
+ * @return the number of nodes in this graph
+ */
+ int get nodeCount => _edges.length;
+
+ /**
+ * Return a set containing the tails of edges that have the given node as their head. The set will
+ * be empty if there are no such edges or if the node is not part of the graph. Clients must not
+ * modify the returned set.
+ *
+ * @param head the node at the head of all of the edges whose tails are to be returned
+ * @return a set containing the tails of edges that have the given node as their head
+ */
+ Set<N> getTails(N head) {
+ Set<N> tails = _edges[head];
+ if (tails == null) {
+ return new Set<N>();
+ }
+ return tails;
+ }
+
+ /**
+ * Return `true` if this graph is empty.
+ *
+ * @return `true` if this graph is empty
+ */
+ bool get isEmpty => _edges.isEmpty;
+
+ /**
+ * Remove all of the given nodes from this graph. As a consequence, any edges for which those
+ * nodes were either a head or a tail will also be removed.
+ *
+ * @param nodes the nodes to be removed
+ */
+ void removeAllNodes(List<N> nodes) {
+ for (N node in nodes) {
+ removeNode(node);
+ }
+ }
+
+ /**
+ * Remove the edge from the given head node to the given tail node. If there was no such edge then
+ * the graph will be unmodified: the number of edges will be the same and the set of nodes will be
+ * the same (neither node will either be added or removed).
+ *
+ * @param head the node at the head of the edge
+ * @param tail the node at the tail of the edge
+ * @return `true` if the graph was modified as a result of this operation
+ */
+ void removeEdge(N head, N tail) {
+ Set<N> tails = _edges[head];
+ if (tails != null) {
+ tails.remove(tail);
+ }
+ }
+
+ /**
+ * Remove the given node from this graph. As a consequence, any edges for which that node was
+ * either a head or a tail will also be removed.
+ *
+ * @param node the node to be removed
+ */
+ void removeNode(N node) {
+ _edges.remove(node);
+ for (Set<N> tails in _edges.values) {
+ tails.remove(node);
+ }
+ }
+
+ /**
+ * Find one node (referred to as a sink node) that has no outgoing edges (that is, for which there
+ * are no edges that have that node as the head of the edge) and remove it from this graph. Return
+ * the node that was removed, or `null` if there are no such nodes either because the graph
+ * is empty or because every node in the graph has at least one outgoing edge. As a consequence of
+ * removing the node from the graph any edges for which that node was a tail will also be removed.
+ *
+ * @return the sink node that was removed
+ */
+ N removeSink() {
+ N sink = _findSink();
+ if (sink == null) {
+ return null;
+ }
+ removeNode(sink);
+ return sink;
+ }
+
+ /**
+ * Return one node that has no outgoing edges (that is, for which there are no edges that have
+ * that node as the head of the edge), or `null` if there are no such nodes.
+ *
+ * @return a sink node
+ */
+ N _findSink() {
+ for (N key in _edges.keys) {
+ if (_edges[key].isEmpty) return key;
+ }
+ return null;
+ }
+}
+
+/**
+ * Instances of the class `NodeInfo` are used by the [SccFinder] to maintain
+ * information about the nodes that have been examined.
+ *
+ * @param N the type of the nodes corresponding to the entries
+ */
+class DirectedGraph_NodeInfo<N> {
+ /**
+ * The depth of this node.
+ */
+ int index = 0;
+
+ /**
+ * The depth of the first node in a cycle.
+ */
+ int lowlink = 0;
+
+ /**
+ * A flag indicating whether the corresponding node is on the stack. Used to remove the need for
+ * searching a collection for the node each time the question needs to be asked.
+ */
+ bool onStack = false;
+
+ /**
+ * The component that contains the corresponding node.
+ */
+ List<N> component;
+
+ /**
+ * Initialize a newly created information holder to represent a node at the given depth.
+ *
+ * @param depth the depth of the node being represented
+ */
+ DirectedGraph_NodeInfo(int depth) {
+ index = depth;
+ lowlink = depth;
+ onStack = false;
+ }
+}
+
+/**
+ * Instances of the class `SccFinder` implement Tarjan's Algorithm for finding the strongly
+ * connected components in a graph.
+ */
+class DirectedGraph_SccFinder<N> {
+ /**
+ * The graph to work with.
+ */
+ DirectedGraph<N> _graph;
+
+ /**
+ * The index used to uniquely identify the depth of nodes.
+ */
+ int _index = 0;
+
+ /**
+ * The stack of nodes that are being visited in order to identify components.
+ */
+ List<N> _stack = new List<N>();
+
+ /**
+ * A table mapping nodes to information about the nodes that is used by this algorithm.
+ */
+ Map<N, DirectedGraph_NodeInfo<N>> _nodeMap = new Map<N, DirectedGraph_NodeInfo<N>>();
+
+ /**
+ * Initialize a newly created finder.
+ */
+ DirectedGraph_SccFinder(DirectedGraph<N> graph) : super() {
+ this._graph = graph;
+ }
+
+ /**
+ * Return a list containing the nodes that are part of the strongly connected component that
+ * contains the given node.
+ *
+ * @param node the node used to identify the strongly connected component to be returned
+ * @return the nodes that are part of the strongly connected component that contains the given
+ * node
+ */
+ List<N> componentContaining(N node) => _strongConnect(node).component;
+
+ /**
+ * Remove and return the top-most element from the stack.
+ *
+ * @return the element that was removed
+ */
+ N _pop() {
+ N node = _stack.removeAt(_stack.length - 1);
+ _nodeMap[node].onStack = false;
+ return node;
+ }
+
+ /**
+ * Add the given node to the stack.
+ *
+ * @param node the node to be added to the stack
+ */
+ void _push(N node) {
+ _nodeMap[node].onStack = true;
+ _stack.add(node);
+ }
+
+ /**
+ * Compute the strongly connected component that contains the given node as well as any
+ * components containing nodes that are reachable from the given component.
+ *
+ * @param v the node from which the search will begin
+ * @return the information about the given node
+ */
+ DirectedGraph_NodeInfo<N> _strongConnect(N v) {
+ //
+ // Set the depth index for v to the smallest unused index
+ //
+ DirectedGraph_NodeInfo<N> vInfo = new DirectedGraph_NodeInfo<N>(_index++);
+ _nodeMap[v] = vInfo;
+ _push(v);
+ //
+ // Consider successors of v
+ //
+ Set<N> tails = _graph._edges[v];
+ if (tails != null) {
+ for (N w in tails) {
+ DirectedGraph_NodeInfo<N> wInfo = _nodeMap[w];
+ if (wInfo == null) {
+ // Successor w has not yet been visited; recurse on it
+ wInfo = _strongConnect(w);
+ vInfo.lowlink = Math.min(vInfo.lowlink, wInfo.lowlink);
+ } else if (wInfo.onStack) {
+ // Successor w is in stack S and hence in the current SCC
+ vInfo.lowlink = Math.min(vInfo.lowlink, wInfo.index);
+ }
+ }
+ }
+ //
+ // If v is a root node, pop the stack and generate an SCC
+ //
+ if (vInfo.lowlink == vInfo.index) {
+ List<N> component = new List<N>();
+ N w;
+ do {
+ w = _pop();
+ component.add(w);
+ _nodeMap[w].component = component;
+ } while (w != v);
+ }
+ return vInfo;
+ }
+}
+
+/**
* The class `ListUtilities` defines utility methods useful for working with [List
].
*/
« no previous file with comments | « pkg/analyzer/lib/src/generated/resolver.dart ('k') | pkg/analyzer/test/generated/ast_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698