1
Fork 0

save-analysis: API-ify impls

This commit is contained in:
Nick Cameron 2015-06-05 17:50:04 +12:00
parent abe5f7b95a
commit 78c25eabd5
2 changed files with 131 additions and 53 deletions

View file

@ -419,19 +419,15 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
id); id);
} }
fn process_trait_ref(&mut self, fn process_trait_ref(&mut self, trait_ref: &ast::TraitRef) {
trait_ref: &ast::TraitRef) { let trait_ref_data = self.save_ctxt.get_trait_ref_data(trait_ref, self.cur_scope);
match self.lookup_type_ref(trait_ref.ref_id) { if let Some(trait_ref_data) = trait_ref_data {
Some(id) => { self.fmt.ref_str(recorder::TypeRef,
let sub_span = self.span.sub_span_for_type_name(trait_ref.path.span); trait_ref.path.span,
self.fmt.ref_str(recorder::TypeRef, Some(trait_ref_data.span),
trait_ref.path.span, trait_ref_data.ref_id,
sub_span, trait_ref_data.scope);
id, visit::walk_path(self, &trait_ref.path);
self.cur_scope);
visit::walk_path(self, &trait_ref.path);
},
None => ()
} }
} }
@ -600,8 +596,9 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
Some(enum_data.span), Some(enum_data.span),
enum_data.id, enum_data.id,
&enum_data.qualname, &enum_data.qualname,
self.cur_scope, enum_data.scope,
&enum_data.value); &enum_data.value);
for variant in &enum_definition.variants { for variant in &enum_definition.variants {
let name = &get_ident(variant.node.name); let name = &get_ident(variant.node.name);
let mut qualname = enum_data.qualname.clone(); let mut qualname = enum_data.qualname.clone();
@ -618,7 +615,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
&qualname, &qualname,
&enum_data.qualname, &enum_data.qualname,
&val, &val,
item.id); enum_data.id);
for arg in args { for arg in args {
self.visit_ty(&*arg.ty); self.visit_ty(&*arg.ty);
} }
@ -635,7 +632,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
&qualname, &qualname,
&enum_data.qualname, &enum_data.qualname,
&val, &val,
item.id); enum_data.id);
for field in &struct_def.fields { for field in &struct_def.fields {
self.process_struct_field_def(field, variant.node.id); self.process_struct_field_def(field, variant.node.id);
@ -644,7 +641,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
} }
} }
} }
self.process_generic_params(ty_params, item.span, &enum_data.qualname, item.id); self.process_generic_params(ty_params, item.span, &enum_data.qualname, enum_data.id);
} else { } else {
self.sess.span_bug(item.span, "expected EnumData"); self.sess.span_bug(item.span, "expected EnumData");
} }
@ -656,43 +653,37 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
trait_ref: &Option<ast::TraitRef>, trait_ref: &Option<ast::TraitRef>,
typ: &ast::Ty, typ: &ast::Ty,
impl_items: &[P<ast::ImplItem>]) { impl_items: &[P<ast::ImplItem>]) {
let trait_id = trait_ref.as_ref().and_then(|tr| self.lookup_type_ref(tr.ref_id)); let impl_data = self.save_ctxt.get_item_data(item);
match typ.node { if let super::Data::ImplData(impl_data) = impl_data {
// Common case impl for a struct or something basic. match impl_data.self_ref {
ast::TyPath(None, ref path) => { Some(ref self_ref) => {
let sub_span = self.span.sub_span_for_type_name(path.span);
let self_id = self.lookup_type_ref(typ.id).map(|id| {
self.fmt.ref_str(recorder::TypeRef, self.fmt.ref_str(recorder::TypeRef,
path.span, item.span,
sub_span, Some(self_ref.span),
id, self_ref.ref_id,
self.cur_scope); self_ref.scope);
id }
}); None => {
self.fmt.impl_str(path.span, self.visit_ty(&typ);
sub_span, }
item.id, }
self_id, if let Some(ref trait_ref_data) = impl_data.trait_ref {
trait_id, self.fmt.ref_str(recorder::TypeRef,
self.cur_scope); item.span,
}, Some(trait_ref_data.span),
_ => { trait_ref_data.ref_id,
// Less useful case, impl for a compound type. trait_ref_data.scope);
self.visit_ty(&*typ); visit::walk_path(self, &trait_ref.as_ref().unwrap().path);
let sub_span = self.span.sub_span_for_type_name(typ.span);
self.fmt.impl_str(typ.span,
sub_span,
item.id,
None,
trait_id,
self.cur_scope);
} }
}
match *trait_ref { self.fmt.impl_str(item.span,
Some(ref trait_ref) => self.process_trait_ref(trait_ref), Some(impl_data.span),
None => (), impl_data.id,
impl_data.self_ref.map(|data| data.ref_id),
impl_data.trait_ref.map(|data| data.ref_id),
impl_data.scope);
} else {
self.sess.span_bug(item.span, "expected ImplData");
} }
self.process_generic_params(type_parameters, item.span, "", item.id); self.process_generic_params(type_parameters, item.span, "", item.id);
@ -717,7 +708,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
&val); &val);
// super-traits // super-traits
for super_bound in trait_refs.iter() { for super_bound in &trait_refs {
let trait_ref = match *super_bound { let trait_ref = match *super_bound {
ast::TraitTyParamBound(ref trait_ref, _) => { ast::TraitTyParamBound(ref trait_ref, _) => {
trait_ref trait_ref
@ -1164,7 +1155,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
self.process_impl(item, self.process_impl(item,
ty_params, ty_params,
trait_ref, trait_ref,
&**typ, &typ,
impl_items) impl_items)
} }
ast::ItemTrait(_, ref generics, ref trait_refs, ref methods) => ast::ItemTrait(_, ref generics, ref trait_refs, ref methods) =>

View file

@ -10,6 +10,7 @@
use session::Session; use session::Session;
use middle::ty; use middle::ty;
use middle::def;
use std::env; use std::env;
use std::fs::{self, File}; use std::fs::{self, File};
@ -55,10 +56,14 @@ pub enum Data {
ModData(ModData), ModData(ModData),
/// Data for Enums. /// Data for Enums.
EnumData(EnumData), EnumData(EnumData),
/// Data for impls.
ImplData(ImplData),
/// Data for the use of some variable (e.g., the use of a local variable, which /// Data for the use of some variable (e.g., the use of a local variable, which
/// will refere to that variables declaration). /// will refere to that variables declaration).
VariableRefData(VariableRefData), VariableRefData(VariableRefData),
/// Data for a reference to a type or trait.
TypeRefData(TypeRefData),
} }
/// Data for all kinds of functions and methods. /// Data for all kinds of functions and methods.
@ -98,6 +103,18 @@ pub struct EnumData {
pub value: String, pub value: String,
pub qualname: String, pub qualname: String,
pub span: Span, pub span: Span,
pub scope: NodeId,
}
pub struct ImplData {
pub id: NodeId,
pub span: Span,
pub scope: NodeId,
// FIXME: I'm not really sure inline data is the best way to do this. Seems
// OK in this case, but generalising leads to returning chunks of AST, which
// feels wrong.
pub trait_ref: Option<TypeRefData>,
pub self_ref: Option<TypeRefData>,
} }
/// Data for the use of some item (e.g., the use of a local variable, which /// Data for the use of some item (e.g., the use of a local variable, which
@ -109,6 +126,13 @@ pub struct VariableRefData {
pub ref_id: DefId, pub ref_id: DefId,
} }
/// Data for a reference to a type or trait.
pub struct TypeRefData {
pub span: Span,
pub scope: NodeId,
pub ref_id: DefId,
}
impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
pub fn new(sess: &'l Session, pub fn new(sess: &'l Session,
@ -211,8 +235,42 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
value: val, value: val,
span: sub_span.unwrap(), span: sub_span.unwrap(),
qualname: enum_name, qualname: enum_name,
scope: self.analysis.ty_cx.map.get_parent(item.id),
}) })
}, },
ast::ItemImpl(_, _, _, ref trait_ref, ref typ, _) => {
let mut type_data = None;
let sub_span;
let parent = self.analysis.ty_cx.map.get_parent(item.id);
match typ.node {
// Common case impl for a struct or something basic.
ast::TyPath(None, ref path) => {
sub_span = self.span_utils.sub_span_for_type_name(path.span);
type_data = self.lookup_ref_id(typ.id).map(|id| TypeRefData {
span: sub_span.unwrap(),
scope: parent,
ref_id: id,
});
},
_ => {
// Less useful case, impl for a compound type.
sub_span = self.span_utils.sub_span_for_type_name(typ.span);
}
}
let trait_data =
trait_ref.as_ref().and_then(|tr| self.get_trait_ref_data(tr, parent));
Data::ImplData(ImplData {
id: item.id,
span: sub_span.unwrap(),
scope: parent,
trait_ref: trait_data,
self_ref: type_data,
})
}
_ => { _ => {
// FIXME // FIXME
unimplemented!(); unimplemented!();
@ -247,6 +305,22 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
} }
} }
// FIXME: we ought to be able to get the parent id ourselves, but we can't
// for now.
pub fn get_trait_ref_data(&self,
trait_ref: &ast::TraitRef,
parent: NodeId)
-> Option<TypeRefData> {
self.lookup_ref_id(trait_ref.ref_id).map(|def_id| {
let sub_span = self.span_utils.sub_span_for_type_name(trait_ref.path.span);
TypeRefData {
span: sub_span.unwrap(),
scope: parent,
ref_id: def_id,
}
})
}
pub fn get_expr_data(&self, expr: &ast::Expr) -> Data { pub fn get_expr_data(&self, expr: &ast::Expr) -> Data {
match expr.node { match expr.node {
ast::ExprField(ref sub_ex, ident) => { ast::ExprField(ref sub_ex, ident) => {
@ -286,6 +360,19 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
// FIXME // FIXME
unimplemented!(); unimplemented!();
} }
fn lookup_ref_id(&self, ref_id: NodeId) -> Option<DefId> {
if !self.analysis.ty_cx.def_map.borrow().contains_key(&ref_id) {
self.sess.bug(&format!("def_map has no key for {} in lookup_type_ref",
ref_id));
}
let def = self.analysis.ty_cx.def_map.borrow().get(&ref_id).unwrap().full_def();
match def {
def::DefPrimTy(_) => None,
_ => Some(def.def_id()),
}
}
} }
// An AST visitor for collecting paths from patterns. // An AST visitor for collecting paths from patterns.