Create some re-usable filtering subroutines.
--- /dev/null
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Code for debugging the dep-graph.
+
+use super::dep_node::DepNode;
+use std::error::Error;
+use std::fmt::Debug;
+
+/// A dep-node filter goes from a user-defined string to a query over
+/// nodes. Right now the format is like this:
+///
+/// x & y & z
+///
+/// where the format-string of the dep-node must contain `x`, `y`, and
+/// `z`.
+#[derive(Debug)]
+pub struct DepNodeFilter {
+ text: String
+}
+
+impl DepNodeFilter {
+ pub fn new(text: &str) -> Self {
+ DepNodeFilter {
+ text: text.trim().to_string()
+ }
+ }
+
+ /// True if all nodes always pass the filter.
+ pub fn accepts_all(&self) -> bool {
+ self.text.is_empty()
+ }
+
+ /// Tests whether `node` meets the filter, returning true if so.
+ pub fn test<D: Clone + Debug>(&self, node: &DepNode<D>) -> bool {
+ let debug_str = format!("{:?}", node);
+ self.text.split("&")
+ .map(|s| s.trim())
+ .all(|f| debug_str.contains(f))
+ }
+}
+
+/// A filter like `F -> G` where `F` and `G` are valid dep-node
+/// filters. This can be used to test the source/target independently.
+pub struct EdgeFilter {
+ pub source: DepNodeFilter,
+ pub target: DepNodeFilter,
+}
+
+impl EdgeFilter {
+ pub fn new(test: &str) -> Result<EdgeFilter, Box<Error>> {
+ let parts: Vec<_> = test.split("->").collect();
+ if parts.len() != 2 {
+ Err(format!("expected a filter like `a&b -> c&d`, not `{}`", test).into())
+ } else {
+ Ok(EdgeFilter {
+ source: DepNodeFilter::new(parts[0]),
+ target: DepNodeFilter::new(parts[1]),
+ })
+ }
+ }
+}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+pub mod debug;
mod dep_node;
mod dep_tracking_map;
mod edges;
use graphviz as dot;
use rustc::dep_graph::{DepGraphQuery, DepNode};
+use rustc::dep_graph::debug::{DepNodeFilter, EdgeFilter};
use rustc::hir::def_id::DefId;
use rustc::ty::TyCtxt;
use rustc_data_structures::fnv::{FnvHashMap, FnvHashSet};
let nodes = match env::var("RUST_DEP_GRAPH_FILTER") {
Ok(string) => {
// Expect one of: "-> target", "source -> target", or "source ->".
- let parts: Vec<_> = string.split("->").collect();
- if parts.len() > 2 {
- bug!("Invalid RUST_DEP_GRAPH_FILTER: expected '[source] -> [target]'");
- }
- let sources = node_set(&query, &parts[0]);
- let targets = node_set(&query, &parts[1]);
+ let edge_filter = EdgeFilter::new(&string).unwrap_or_else(|e| {
+ bug!("invalid filter: {}", e)
+ });
+ let sources = node_set(&query, &edge_filter.source);
+ let targets = node_set(&query, &edge_filter.target);
filter_nodes(&query, &sources, &targets)
}
Err(_) => {
// Given an optional filter like `"x,y,z"`, returns either `None` (no
// filter) or the set of nodes whose labels contain all of those
// substrings.
-fn node_set(query: &DepGraphQuery<DefId>, filter: &str)
+fn node_set(query: &DepGraphQuery<DefId>, filter: &DepNodeFilter)
-> Option<FnvHashSet<DepNode<DefId>>>
{
debug!("node_set(filter={:?})", filter);
- if filter.trim().is_empty() {
+ if filter.accepts_all() {
return None;
}
- let filters: Vec<&str> = filter.split("&").map(|s| s.trim()).collect();
-
- debug!("node_set: filters={:?}", filters);
-
- Some(query.nodes()
- .into_iter()
- .filter(|n| {
- let s = format!("{:?}", n);
- filters.iter().all(|f| s.contains(f))
- })
- .collect())
+ Some(query.nodes().into_iter().filter(|n| filter.test(n)).collect())
}
fn filter_nodes(query: &DepGraphQuery<DefId>,