save-analysis: API-ify impls
This commit is contained in:
parent
abe5f7b95a
commit
78c25eabd5
2 changed files with 131 additions and 53 deletions
|
@ -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) =>
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue