Skip to content

Instantly share code, notes, and snippets.

@pmsanford
Created December 20, 2014 00:30
Show Gist options
  • Save pmsanford/066697b08e59e6bd3893 to your computer and use it in GitHub Desktop.
Save pmsanford/066697b08e59e6bd3893 to your computer and use it in GitHub Desktop.
extern crate syntax;
extern crate rustc;
use syntax::diagnostic::SpanHandler;
use syntax::codemap::Span;
use syntax::ast::{Item, Item_};
struct StructPkg {
pub name: String,
pub def: Item,
pub impls: Vec<Item>
}
impl StructPkg {
pub fn from_item(itm: &Item) -> StructPkg {
let name = String::from_str(itm.ident.name.as_str());
let def = itm.clone();
let impls: Vec<Item> = Vec::new();
StructPkg {
name: name,
def: def,
impls: impls
}
}
}
enum AstItem {
StructDef(StructPkg),
Other(Span)
}
fn main() {
use std::io;
use std::io::Reader as rdr;
use std::str;
use syntax::parse;
use syntax::parse::parser::Parser;
use syntax::diagnostics::registry::Registry;
use rustc::session;
use rustc::session::config::{
CrateType, Options
};
use syntax::parse::lexer;
use std::collections::HashMap;
use syntax::codemap::{BytePos, ExpnId};
let opt = Options {
crate_types: vec![CrateType::CrateTypeRlib],
.. session::config::basic_options()
};
let reg = Registry::new(&rustc::DIAGNOSTICS);
let session = session::build_session(opt, None, reg);
let cfg = session::config::build_configuration(&session);
let sess = parse::new_parse_sess();
let source = io::stdin().read_to_end().unwrap();
let str_src = str::from_utf8(source.as_slice()).unwrap();
let fm = parse::string_to_filemap(&sess, str_src.to_string(),
"<stdin>".to_string());
let lexer = lexer::StringReader::new(&sess.span_diagnostic,
fm);
let lex_ptr = box lexer;
let mut parsr = Parser::new(&sess, cfg, lex_ptr);
let cr = parsr.parse_crate_mod();
let mut hm = HashMap::new();
for item_ptr in cr.module.items.iter() {
match item_ptr.node {
Item_::ItemStruct(_, _) => {
let spkg = StructPkg::from_item(item_ptr.deref());
hm.insert(spkg.name.clone(), AstItem::StructDef(spkg));
},
Item_::ItemImpl(_, _, _, _, _) => {},
_ => {
hm.insert(String::from_str(item_ptr.ident.name.as_str()),
AstItem::Other(item_ptr.span));
}
}
}
for item_ptr in cr.module.items.iter() {
match item_ptr.node {
Item_::ItemImpl(_, _, Some(_), _, _) => {
let name = String::from_str(item_ptr.ident.name.as_str());
let name_pieces: Vec<&str> = name.split('.').collect();
let name_str = String::from_str(name_pieces[0]);
if let AstItem::StructDef(ref mut spkg) =
*hm.get_mut(&name_str).unwrap() {
spkg.impls.push(item_ptr.deref().clone());
}
},
Item_::ItemImpl(_, _, _, _, _) => {
if let AstItem::StructDef(ref mut spkg) =
*hm.get_mut(&String::from_str(item_ptr.ident.name.as_str()))
.unwrap() {
spkg.impls.push(item_ptr.deref().clone());
}
},
_ => {}
}
}
let first_spn_start = {
let mut start = cr.module.items[0].span.lo;
if start != BytePos(0u32) {
start = start - BytePos(1u32);
for item_ptr in cr.module.items.iter() {
if item_ptr.span.lo < start {
if item_ptr.span.lo == BytePos(0u32) {
start = BytePos(0u32);
break;
}
start = item_ptr.span.lo - BytePos(1u32);
}
}
}
start
};
let opening_spn = Span {
lo: BytePos(0u32),
hi: first_spn_start,
expn_id: ExpnId::from_llvm_cookie(0)
};
println!("{}", txt(&opening_spn, &sess.span_diagnostic));
for (_, enm) in hm.iter() {
match *enm {
AstItem::StructDef(ref itm) => {
println!("{}",
txt(&itm.def.span, &sess.span_diagnostic));
for impl_itm in itm.impls.iter() {
println!("");
println!("{}", txt(&impl_itm.span, &sess.span_diagnostic));
}
println!("");
},
AstItem::Other(spn) => {
println!("{}", txt(&spn, &sess.span_diagnostic));
println!("");
}
}
}
}
fn txt(sp: &Span, sh: &SpanHandler) -> String {
sh.cm.span_to_snippet(*sp).unwrap()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment