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

View file

@ -10,6 +10,7 @@
use session::Session;
use middle::ty;
use middle::def;
use std::env;
use std::fs::{self, File};
@ -55,10 +56,14 @@ pub enum Data {
ModData(ModData),
/// Data for Enums.
EnumData(EnumData),
/// Data for impls.
ImplData(ImplData),
/// Data for the use of some variable (e.g., the use of a local variable, which
/// will refere to that variables declaration).
VariableRefData(VariableRefData),
/// Data for a reference to a type or trait.
TypeRefData(TypeRefData),
}
/// Data for all kinds of functions and methods.
@ -98,6 +103,18 @@ pub struct EnumData {
pub value: String,
pub qualname: String,
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
@ -109,6 +126,13 @@ pub struct VariableRefData {
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> {
pub fn new(sess: &'l Session,
@ -211,8 +235,42 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
value: val,
span: sub_span.unwrap(),
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
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 {
match expr.node {
ast::ExprField(ref sub_ex, ident) => {
@ -286,6 +360,19 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
// FIXME
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.