save-analysis: API-ify paths

This commit is contained in:
Nick Cameron 2015-07-08 14:30:18 +12:00
parent 84cb4ad969
commit 374af4aea7
3 changed files with 147 additions and 86 deletions

View file

@ -28,7 +28,7 @@
//! 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;
@ -738,90 +738,51 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
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);
@ -1187,7 +1148,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
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) =>
@ -1283,6 +1244,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, immut, ref_kind) in &collector.collected_paths {
let def_map = self.tcx.def_map.borrow();
@ -1319,11 +1281,12 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
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) {

View file

@ -61,6 +61,8 @@ pub enum Data {
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),
}
@ -122,7 +124,7 @@ pub struct ImplData {
}
/// 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,
@ -139,6 +141,14 @@ pub struct TypeRefData {
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 {
@ -392,13 +402,17 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
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!();
@ -406,6 +420,90 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
}
}
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,

View file

@ -61,7 +61,7 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
// Keep going, outside-in.
let fully_expanded = fld.fold_expr(expanded_expr);
let span = fld.new_span(span);
let span = fld.new_span(span);
fld.cx.bt_pop();
fully_expanded.map(|e| ast::Expr {