//! DumpCsvVisitor walks the AST and processes it.
-use super::{escape, generated_code, recorder, SaveContext, PathCollector};
+use super::{escape, generated_code, recorder, SaveContext, PathCollector, Data};
use session::Session;
fn process_path(&mut self,
id: NodeId,
- span: Span,
path: &ast::Path,
ref_kind: Option<recorder::Row>) {
- if generated_code(span) {
- return
+ if generated_code(path.span) {
+ return;
}
- let def_map = self.tcx.def_map.borrow();
- if !def_map.contains_key(&id) {
- self.sess.span_bug(span,
- &format!("def_map has no key for {} in visit_expr", id));
- }
- let def = def_map.get(&id).unwrap().full_def();
- let sub_span = self.span.span_for_last_ident(span);
- match def {
- def::DefUpvar(..) |
- def::DefLocal(..) |
- def::DefStatic(..) |
- def::DefConst(..) |
- def::DefAssociatedConst(..) |
- def::DefVariant(..) => self.fmt.ref_str(ref_kind.unwrap_or(recorder::VarRef),
- span,
- sub_span,
- def.def_id(),
- self.cur_scope),
- def::DefStruct(def_id) => self.fmt.ref_str(recorder::TypeRef,
- span,
- sub_span,
- def_id,
- self.cur_scope),
- def::DefTy(def_id, _) => self.fmt.ref_str(recorder::TypeRef,
- span,
- sub_span,
- def_id,
- self.cur_scope),
- def::DefMethod(declid, provenence) => {
- let sub_span = self.span.sub_span_for_meth_name(span);
- let defid = if declid.krate == ast::LOCAL_CRATE {
- let ti = self.tcx.impl_or_trait_item(declid);
- match provenence {
- def::FromTrait(def_id) => {
- Some(self.tcx.trait_items(def_id)
- .iter()
- .find(|mr| {
- mr.name() == ti.name()
- })
- .unwrap()
- .def_id())
- }
- def::FromImpl(def_id) => {
- let impl_items = self.tcx.impl_items.borrow();
- Some(impl_items.get(&def_id)
- .unwrap()
- .iter()
- .find(|mr| {
- self.tcx.impl_or_trait_item(mr.def_id()).name()
- == ti.name()
- })
- .unwrap()
- .def_id())
- }
- }
- } else {
- None
- };
- self.fmt.meth_call_str(span,
- sub_span,
- defid,
- Some(declid),
- self.cur_scope);
- },
- def::DefFn(def_id, _) => {
- self.fmt.fn_call_str(span,
- sub_span,
- def_id,
- self.cur_scope)
+ let path_data = self.save_ctxt.get_path_data(id, path);
+ match path_data {
+ Data::VariableRefData(ref vrd) => {
+ self.fmt.ref_str(ref_kind.unwrap_or(recorder::VarRef),
+ path.span,
+ Some(vrd.span),
+ vrd.ref_id,
+ vrd.scope);
+
+ }
+ Data::TypeRefData(ref trd) => {
+ self.fmt.ref_str(recorder::TypeRef,
+ path.span,
+ Some(trd.span),
+ trd.ref_id,
+ trd.scope);
+ }
+ Data::MethodCallData(ref mcd) => {
+ self.fmt.meth_call_str(path.span,
+ Some(mcd.span),
+ mcd.ref_id,
+ mcd.decl_id,
+ mcd.scope);
+ }
+ Data::FunctionCallData(fcd) => {
+ self.fmt.fn_call_str(path.span,
+ Some(fcd.span),
+ fcd.ref_id,
+ fcd.scope);
+ }
+ _ => {
+ self.sess.span_bug(path.span,
+ &format!("Unexpected data: {:?}", path_data));
}
- _ => self.sess.span_bug(span,
- &format!("Unexpected def kind while looking \
- up path in `{}`: `{:?}`",
- self.span.snippet(span),
- def)),
}
- // modules or types in the path prefix
+
+ // Modules or types in the path prefix.
+ let def_map = self.tcx.def_map.borrow();
+ let def = def_map.get(&id).unwrap().full_def();
match def {
def::DefMethod(did, _) => {
let ti = self.tcx.impl_or_trait_item(did);
visit::walk_expr(self, ex);
}
ast::ExprPath(_, ref path) => {
- self.process_path(ex.id, path.span, path, None);
+ self.process_path(ex.id, path, None);
visit::walk_expr(self, ex);
}
ast::ExprStruct(ref path, ref fields, ref base) =>
// 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, immut, ref_kind) in &collector.collected_paths {
let def_map = self.tcx.def_map.borrow();
def)
}
}
+
for &(id, ref path, ref_kind) in &paths_to_process {
- self.process_path(id, path.span, path, ref_kind);
+ self.process_path(id, path, ref_kind);
}
visit::walk_expr_opt(self, &arm.guard);
- self.visit_expr(&*arm.body);
+ self.visit_expr(&arm.body);
}
fn visit_stmt(&mut self, s: &ast::Stmt) {
VariableRefData(VariableRefData),
/// Data for a reference to a type or trait.
TypeRefData(TypeRefData),
+ /// Data about a function call.
+ FunctionCallData(FunctionCallData),
/// Data about a method call.
MethodCallData(MethodCallData),
}
}
/// Data for the use of some item (e.g., the use of a local variable, which
-/// will refere to that variables declaration (by ref_id)).
+/// will refer to that variables declaration (by ref_id)).
#[derive(Debug)]
pub struct VariableRefData {
pub name: String,
pub ref_id: DefId,
}
+/// Data about a function call.
+#[derive(Debug)]
+pub struct FunctionCallData {
+ pub span: Span,
+ pub scope: NodeId,
+ pub ref_id: DefId,
+}
+
/// Data about a method call.
#[derive(Debug)]
pub struct MethodCallData {
ty::TraitContainer(_) => (None, Some(method_id))
};
let sub_span = self.span_utils.sub_span_for_meth_name(expr.span);
+ let parent = self.tcx.map.get_enclosing_scope(expr.id).unwrap_or(0);
Some(Data::MethodCallData(MethodCallData {
span: sub_span.unwrap(),
- scope: self.tcx.map.get_enclosing_scope(expr.id).unwrap_or(0),
+ scope: parent,
ref_id: def_id,
- decl_id: decl_id,
+ decl_id: decl_id,
}))
}
+ ast::ExprPath(_, ref path) => {
+ Some(self.get_path_data(expr.id, path))
+ }
_ => {
// FIXME
unimplemented!();
}
}
+ pub fn get_path_data(&self,
+ id: NodeId,
+ path: &ast::Path)
+ -> Data {
+ let def_map = self.tcx.def_map.borrow();
+ if !def_map.contains_key(&id) {
+ self.tcx.sess.span_bug(path.span,
+ &format!("def_map has no key for {} in visit_expr", id));
+ }
+ let def = def_map.get(&id).unwrap().full_def();
+ let sub_span = self.span_utils.span_for_last_ident(path.span);
+ match def {
+ def::DefUpvar(..) |
+ def::DefLocal(..) |
+ def::DefStatic(..) |
+ def::DefConst(..) |
+ def::DefAssociatedConst(..) |
+ def::DefVariant(..) => {
+ Data::VariableRefData(VariableRefData {
+ name: self.span_utils.snippet(sub_span.unwrap()),
+ span: sub_span.unwrap(),
+ scope: self.tcx.map.get_enclosing_scope(id).unwrap_or(0),
+ ref_id: def.def_id(),
+ })
+ }
+ def::DefStruct(def_id) | def::DefTy(def_id, _) => {
+ Data::TypeRefData(TypeRefData {
+ span: sub_span.unwrap(),
+ ref_id: def_id,
+ scope: self.tcx.map.get_enclosing_scope(id).unwrap_or(0),
+ })
+ }
+ def::DefMethod(decl_id, provenence) => {
+ let sub_span = self.span_utils.sub_span_for_meth_name(path.span);
+ let def_id = if decl_id.krate == ast::LOCAL_CRATE {
+ let ti = self.tcx.impl_or_trait_item(decl_id);
+ match provenence {
+ def::FromTrait(def_id) => {
+ Some(self.tcx.trait_items(def_id)
+ .iter()
+ .find(|mr| {
+ mr.name() == ti.name()
+ })
+ .unwrap()
+ .def_id())
+ }
+ def::FromImpl(def_id) => {
+ let impl_items = self.tcx.impl_items.borrow();
+ Some(impl_items.get(&def_id)
+ .unwrap()
+ .iter()
+ .find(|mr| {
+ self.tcx.impl_or_trait_item(mr.def_id()).name()
+ == ti.name()
+ })
+ .unwrap()
+ .def_id())
+ }
+ }
+ } else {
+ None
+ };
+ Data::MethodCallData(MethodCallData {
+ span: sub_span.unwrap(),
+ scope: self.tcx.map.get_enclosing_scope(id).unwrap_or(0),
+ ref_id: def_id,
+ decl_id: Some(decl_id),
+ })
+ },
+ def::DefFn(def_id, _) => {
+ Data::FunctionCallData(FunctionCallData {
+ ref_id: def_id,
+ span: sub_span.unwrap(),
+ scope: self.tcx.map.get_enclosing_scope(id).unwrap_or(0),
+ })
+ }
+ _ => self.tcx.sess.span_bug(path.span,
+ &format!("Unexpected def kind while looking \
+ up path in `{}`: `{:?}`",
+ self.span_utils.snippet(path.span),
+ def)),
+ }
+ }
+
pub fn get_field_ref_data(&self,
field_ref: &ast::Field,
struct_id: DefId,