Last active
January 3, 2016 08:58
-
-
Save klutzy/8439132 to your computer and use it in GitHub Desktop.
broken dependency graph impl
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#[feature(managed_boxes)]; | |
extern mod extra; | |
extern mod syntax; | |
extern mod rustc; | |
use std::os::args; | |
use std::hashmap::{HashMap, HashSet}; | |
use syntax::ast; | |
use syntax::ast_map; | |
use syntax::ast_util; | |
use syntax::ast_map::Node; | |
use syntax::visit; | |
use syntax::parse::token::get_ident_interner; | |
use syntax::codemap::Span; | |
use syntax::visit::Visitor; | |
use rustc::driver::driver; | |
use rustc::driver::session; | |
use rustc::middle::typeck; | |
struct RotVisitor<'a> { | |
map: HashSet<(ast::NodeId, ast::NodeId)>, // from -> to | |
cur_id: ast::NodeId, | |
def_map: &'a HashMap<ast::NodeId, ast::Def>, | |
method_map: &'a HashMap<ast::NodeId, typeck::method_map_entry>, | |
} | |
impl<'a> Visitor<()> for RotVisitor<'a> { | |
fn visit_fn(&mut self, fk: &visit::FnKind, decl: &ast::FnDecl, | |
body: &ast::Block, span: Span, id: ast::NodeId, _: ()) { | |
let old_id = id; | |
match fk { | |
&visit::FkFnBlock => {}, | |
_ => { | |
self.cur_id = id; | |
} | |
} | |
visit::walk_fn(self, fk, decl, body, span, id, ()); | |
self.cur_id = old_id; | |
} | |
fn visit_path(&mut self, path: &ast::Path, id: ast::NodeId, _: ()) { | |
if self.cur_id != -1 { | |
let t_node_id = path_to_node_id(self.def_map, id); | |
self.map.insert((self.cur_id, t_node_id)); | |
} | |
visit::walk_path(self, path, ()); | |
} | |
fn visit_expr(&mut self, e: &ast::Expr, _: ()) { | |
match e.node { | |
ast::ExprMethodCall(..) => { | |
match self.method_map.find(&e.id) { | |
Some(&typeck::method_map_entry { origin, .. }) => { | |
let node_id = match origin { | |
typeck::method_static(def_id) => def_id.node, | |
typeck::method_param(param) => param.trait_id.node, | |
typeck::method_object(obj) => obj.trait_id.node, | |
}; | |
self.map.insert((self.cur_id, node_id)); | |
} | |
None => {}, | |
} | |
} | |
_ => {} | |
} | |
visit::walk_expr(self, e, ()); | |
} | |
} | |
fn node_id_to_name(a: &HashMap<ast::NodeId, Node>, id: ast::NodeId) -> Option<~str> { | |
let interner = get_ident_interner(); | |
match a.find(&id) { | |
None => None, | |
Some(&ast_map::NodeItem(item, path)) => { | |
Some(ast_map::path_ident_to_str(path, item.ident, interner)) | |
}, | |
Some(&ast_map::NodeMethod(m, _, path)) => { | |
Some(format!("{}::{}", | |
ast_map::path_to_str(*path, interner), interner.get(m.ident.name))) | |
}, | |
s => { | |
None | |
}, | |
} | |
} | |
fn path_to_node_id(def_map: &HashMap<ast::NodeId, ast::Def>, id: ast::NodeId) -> ast::NodeId { | |
let def = match def_map.find(&id) { | |
Some(&def) => def, | |
_ => return -1, | |
}; | |
let def_id = match def { | |
ast::DefVariant(enum_id, _, _) => enum_id, | |
ast::DefPrimTy(_) => return -1, | |
_ => ast_util::def_id_of_def(def), | |
}; | |
def_id.node | |
} | |
fn main() { | |
do rustc::monitor |demitter| { | |
let mut args = args(); | |
let binary = args.shift(); | |
let matches = extra::getopts::groups::getopts(args, driver::optgroups()).ok().unwrap(); | |
let filename = matches.free[0].as_slice(); | |
let f = Path::new(filename); | |
let sopts = driver::build_session_options(binary, &matches, demitter); | |
let sess = driver::build_session(sopts, demitter); | |
let cfg = driver::build_configuration(sess); | |
let input = &driver::file_input(f); | |
let (crate, ast_map) = { | |
let crate = driver::phase_1_parse_input(sess, cfg.clone(), input); | |
if driver::stop_after_phase_1(sess) { | |
return; | |
} | |
let res = driver::phase_2_configure_and_expand(sess, cfg, crate); | |
res | |
}; | |
let _outputs = driver::build_output_filenames(input, &None, &None, crate.attrs, sess); | |
//driver::write_out_deps(sess, input, outputs, &crate); | |
if driver::stop_after_phase_2(sess) { | |
return; | |
} | |
rustc::metadata::creader::read_crates(sess, &crate, | |
session::sess_os_to_meta_os(sess.targ_cfg.os), | |
get_ident_interner()); | |
let lang_items = rustc::middle::lang_items::collect_language_items(&crate, sess); | |
let crate_map = rustc::middle::resolve::resolve_crate(sess, lang_items, &crate); | |
let rustc::middle::resolve::CrateMap { | |
def_map: def_map, | |
exp_map2: _exp_map2, | |
trait_map: trait_map, | |
external_exports: _external_exports, | |
last_private_map: _last_private_map, | |
} = crate_map; | |
let named_region_map = rustc::middle::resolve_lifetime::crate(sess, &crate); | |
let free_vars = rustc::middle::freevars::annotate_freevars(def_map, &crate); | |
let region_map = rustc::middle::region::resolve_crate(sess, &crate); | |
let ty_cx = rustc::middle::ty::mk_ctxt(sess, def_map, named_region_map, | |
ast_map, free_vars, | |
region_map, lang_items); | |
let (method_map, _vtable_map) = typeck::check_crate(ty_cx, | |
trait_map, | |
&crate); | |
let items = ty_cx.items.borrow(); | |
let items = items.get(); | |
let def_map = def_map.borrow(); | |
let def_map = def_map.get(); | |
let method_map = method_map.borrow(); | |
let method_map = method_map.get(); | |
let mut visitor = RotVisitor { | |
map: HashSet::new(), | |
cur_id: -1, | |
def_map: def_map, | |
method_map: method_map, | |
}; | |
visit::walk_crate(&mut visitor, &crate, ()); | |
println!("digraph \\{"); | |
for &(f, t) in visitor.map.iter() { | |
let f_name = node_id_to_name(items, f); | |
let t_name = node_id_to_name(items, t); | |
if f_name.is_none() || t_name.is_none() { | |
continue; | |
} | |
println!(" \"{}\" -> \"{}\";", f_name.unwrap(), t_name.unwrap()); | |
} | |
println!("\\}"); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#[crate_type = "lib"]; | |
trait T { | |
fn d(&self) {} | |
fn t(&self); | |
} | |
struct A; | |
impl T for A { | |
fn t(&self) {} | |
} | |
impl A { | |
fn a(&self) {} | |
fn b() {} | |
} | |
fn f() { | |
A.a(); | |
A::b(); | |
A.t(); | |
A.d(); | |
} | |
fn g() { f(); f(); } | |
fn h() { f(); g(); } | |
fn n() { | |
do spawn { | |
g(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment