diff --git a/src/librustc_trans/save/dump_csv.rs b/src/librustc_trans/save/dump_csv.rs index 798c35874eeb..7f66d3a833fd 100644 --- a/src/librustc_trans/save/dump_csv.rs +++ b/src/librustc_trans/save/dump_csv.rs @@ -89,7 +89,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> { sess: sess, err_count: Cell::new(0) }), - cur_scope: 0 + cur_scope: 0 } } @@ -108,7 +108,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> { // Dump info about all the external crates referenced from this crate. for c in &self.save_ctxt.get_external_crates() { - self.fmt.external_crate_str(krate.span, &c.name, c.number); + self.fmt.external_crate_str(krate.span, &c.name, c.number); } self.fmt.recorder.record("end_external_crates\n"); } @@ -496,58 +496,52 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> { decl: &ast::FnDecl, ty_params: &ast::Generics, body: &ast::Block) { - let qualname = format!("::{}", self.analysis.ty_cx.map.path_to_string(item.id)); + let fn_data = self.save_ctxt.get_item_data(item); + if let super::Data::FunctionData(fn_data) = fn_data { + self.fmt.fn_str(item.span, + Some(fn_data.span), + fn_data.id, + &fn_data.qualname, + fn_data.scope); - let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Fn); - self.fmt.fn_str(item.span, - sub_span, - item.id, - &qualname[..], - self.cur_scope); - self.process_formals(&decl.inputs, &qualname[..]); + self.process_formals(&decl.inputs, &fn_data.qualname); + self.process_generic_params(ty_params, item.span, &fn_data.qualname, item.id); + } else { + unreachable!(); + } - // walk arg and return types for arg in &decl.inputs { - self.visit_ty(&*arg.ty); + self.visit_ty(&arg.ty); } if let ast::Return(ref ret_ty) = decl.output { - self.visit_ty(&**ret_ty); + self.visit_ty(&ret_ty); } - // walk the body - self.nest(item.id, |v| v.visit_block(&*body)); - - self.process_generic_params(ty_params, item.span, &qualname[..], item.id); + self.nest(item.id, |v| v.visit_block(&body)); } - fn process_static(&mut self, - item: &ast::Item, - typ: &ast::Ty, - mt: ast::Mutability, - expr: &ast::Expr) + fn process_static_or_const_item(&mut self, + item: &ast::Item, + typ: &ast::Ty, + expr: &ast::Expr) { - let qualname = format!("::{}", self.analysis.ty_cx.map.path_to_string(item.id)); + let var_data = self.save_ctxt.get_item_data(item); + if let super::Data::VariableData(var_data) = var_data { + self.fmt.static_str(item.span, + Some(var_data.span), + var_data.id, + &var_data.name, + &var_data.qualname, + &var_data.value, + &var_data.type_value, + var_data.scope); + } else { + unreachable!(); + } - // If the variable is immutable, save the initialising expression. - let (value, keyword) = match mt { - ast::MutMutable => (String::from_str(""), keywords::Mut), - ast::MutImmutable => (self.span.snippet(expr.span), keywords::Static), - }; - - let sub_span = self.span.sub_span_after_keyword(item.span, keyword); - self.fmt.static_str(item.span, - sub_span, - item.id, - &get_ident(item.ident), - &qualname[..], - &value[..], - &ty_to_string(&*typ), - self.cur_scope); - - // walk type and init value - self.visit_ty(&*typ); + self.visit_ty(&typ); self.visit_expr(expr); } @@ -562,12 +556,13 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> { let sub_span = self.span.sub_span_after_keyword(span, keywords::Const); + self.fmt.static_str(span, sub_span, id, &get_ident((*ident).clone()), &qualname[..], - "", + &self.span.snippet(expr.span), &ty_to_string(&*typ), self.cur_scope); @@ -1174,10 +1169,10 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> { } ast::ItemFn(ref decl, _, _, ref ty_params, ref body) => self.process_fn(item, &**decl, ty_params, &**body), - ast::ItemStatic(ref typ, mt, ref expr) => - self.process_static(item, &**typ, mt, &**expr), + ast::ItemStatic(ref typ, _, ref expr) => + self.process_static_or_const_item(item, typ, expr), ast::ItemConst(ref typ, ref expr) => - self.process_const(item.id, &item.ident, item.span, &*typ, &*expr), + self.process_static_or_const_item(item, &typ, &expr), ast::ItemStruct(ref def, ref ty_params) => self.process_struct(item, &**def, ty_params), ast::ItemEnum(ref def, ref ty_params) => self.process_enum(item, def, ty_params), ast::ItemImpl(_, _, @@ -1378,7 +1373,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> { }, _ => { visit::walk_expr(self, ex) - }, + } } } @@ -1401,7 +1396,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> { // This is to get around borrow checking, because we need mut self to call process_path. let mut paths_to_process = vec![]; // process collected paths - for &(id, ref p, ref immut, ref_kind) in &collector.collected_paths { + for &(id, ref p, immut, ref_kind) in &collector.collected_paths { let def_map = self.analysis.ty_cx.def_map.borrow(); if !def_map.contains_key(&id) { self.sess.span_bug(p.span, @@ -1411,7 +1406,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> { let def = def_map.get(&id).unwrap().full_def(); match def { def::DefLocal(id) => { - let value = if *immut { + let value = if immut == ast::MutImmutable { self.span.snippet(p.span).to_string() } else { "".to_string() @@ -1464,8 +1459,12 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> { let value = self.span.snippet(l.span); - for &(id, ref p, ref immut, _) in &collector.collected_paths { - let value = if *immut { value.to_string() } else { "".to_string() }; + for &(id, ref p, immut, _) in &collector.collected_paths { + let value = if immut == ast::MutImmutable { + value.to_string() + } else { + "".to_string() + }; let types = self.analysis.ty_cx.node_types(); let typ = ppaux::ty_to_string(&self.analysis.ty_cx, *types.get(&id).unwrap()); // Get the span only for the name of the variable (I hope the path diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs index dc1c36bd0011..7e503c6819ba 100644 --- a/src/librustc_trans/save/mod.rs +++ b/src/librustc_trans/save/mod.rs @@ -19,8 +19,10 @@ use syntax::{attr}; use syntax::ast::{self, NodeId, DefId}; use syntax::ast_util; use syntax::codemap::*; -use syntax::parse::token::keywords; +use syntax::parse::token::{self, get_ident, keywords}; use syntax::visit::{self, Visitor}; +use syntax::print::pprust::ty_to_string; + use self::span_utils::SpanUtils; @@ -40,18 +42,32 @@ pub struct CrateData { pub number: u32, } +// Data for any entity in the Rust language. The actual data contained varied +// with the kind of entity being queried. See the nested structs for details. pub enum Data { FunctionData(FunctionData), + VariableData(VariableData), } pub struct FunctionData { pub id: NodeId, + pub name: String, pub qualname: String, pub declaration: Option, pub span: Span, pub scope: NodeId, } +pub struct VariableData { + pub id: NodeId, + pub name: String, + pub qualname: String, + pub span: Span, + pub scope: NodeId, + pub value: String, + pub type_value: String, +} + impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { pub fn new(sess: &'l Session, analysis: &'l ty::CrateAnalysis<'tcx>, @@ -78,35 +94,71 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { pub fn get_item_data(&self, item: &ast::Item) -> Data { match item.node { ast::Item_::ItemFn(..) => { - let qualname = format!("::{}", self.analysis.ty_cx.map.path_to_string(item.id)); + let name = self.analysis.ty_cx.map.path_to_string(item.id); + let qualname = format!("::{}", name); let sub_span = self.span_utils.sub_span_after_keyword(item.span, keywords::Fn); Data::FunctionData(FunctionData { id: item.id, + name: name, qualname: qualname, declaration: None, span: sub_span.unwrap(), scope: self.analysis.ty_cx.map.get_parent(item.id), }) } + ast::ItemStatic(ref typ, mt, ref expr) => { + let qualname = format!("::{}", self.analysis.ty_cx.map.path_to_string(item.id)); + + // If the variable is immutable, save the initialising expression. + let value = match mt { + ast::MutMutable => String::from_str(""), + ast::MutImmutable => self.span_utils.snippet(expr.span), + }; + + let sub_span = self.span_utils.sub_span_after_keyword(item.span, keywords::Static); + + Data::VariableData(VariableData { + id: item.id, + name: get_ident(item.ident).to_string(), + qualname: qualname, + span: sub_span.unwrap(), + scope: self.analysis.ty_cx.map.get_parent(item.id), + value: value, + type_value: ty_to_string(&typ), + }) + } + ast::ItemConst(ref typ, ref expr) => { + let qualname = format!("::{}", self.analysis.ty_cx.map.path_to_string(item.id)); + let sub_span = self.span_utils.sub_span_after_keyword(item.span, keywords::Const); + + Data::VariableData(VariableData { + id: item.id, + name: get_ident(item.ident).to_string(), + qualname: qualname, + span: sub_span.unwrap(), + scope: self.analysis.ty_cx.map.get_parent(item.id), + value: self.span_utils.snippet(expr.span), + type_value: ty_to_string(&typ), + }) + } _ => { + // FIXME unimplemented!(); } } } - pub fn get_data_for_id(&self, id: &NodeId) -> Data { - // TODO - unimplemented!(); + pub fn get_data_for_id(&self, _id: &NodeId) -> Data { + // FIXME + unimplemented!(); } } // An AST visitor for collecting paths from patterns. struct PathCollector { - // TODO bool -> ast::mutable - // TODO recorder -> var kind new enum - // The Row field identifies the kind of formal variable. - collected_paths: Vec<(NodeId, ast::Path, bool, recorder::Row)>, + // The Row field identifies the kind of pattern. + collected_paths: Vec<(NodeId, ast::Path, ast::Mutability, recorder::Row)>, } impl PathCollector { @@ -119,29 +171,35 @@ impl PathCollector { impl<'v> Visitor<'v> for PathCollector { fn visit_pat(&mut self, p: &ast::Pat) { + if generated_code(p.span) { + return; + } + match p.node { ast::PatStruct(ref path, _, _) => { - self.collected_paths.push((p.id, path.clone(), false, recorder::StructRef)); + self.collected_paths.push((p.id, + path.clone(), + ast::MutMutable, + recorder::StructRef)); } ast::PatEnum(ref path, _) | ast::PatQPath(_, ref path) => { - self.collected_paths.push((p.id, path.clone(), false, recorder::VarRef)); + self.collected_paths.push((p.id, path.clone(), ast::MutMutable, recorder::VarRef)); } ast::PatIdent(bm, ref path1, _) => { + debug!("PathCollector, visit ident in pat {}: {:?} {:?}", + token::get_ident(path1.node), + p.span, + path1.span); let immut = match bm { // Even if the ref is mut, you can't change the ref, only // the data pointed at, so showing the initialising expression // is still worthwhile. - ast::BindByRef(_) => true, - ast::BindByValue(mt) => { - match mt { - ast::MutMutable => false, - ast::MutImmutable => true, - } - } + ast::BindByRef(_) => ast::MutImmutable, + ast::BindByValue(mt) => mt, }; // collect path for either visit_local or visit_arm - let path = ast_util::ident_to_path(path1.span,path1.node); + let path = ast_util::ident_to_path(path1.span, path1.node); self.collected_paths.push((p.id, path, immut, recorder::VarRef)); } _ => {} diff --git a/src/librustc_trans/save/recorder.rs b/src/librustc_trans/save/recorder.rs index db724b0ef6b6..193902d981d6 100644 --- a/src/librustc_trans/save/recorder.rs +++ b/src/librustc_trans/save/recorder.rs @@ -62,6 +62,9 @@ macro_rules! svec { }) } +// FIXME recorder should operate on super::Data, rather than lots of ad hoc +// data. + #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum Row { Variable,