save-analysis: use a macro for 'downcasting'

This commit is contained in:
Nick Cameron 2015-06-09 10:36:30 +12:00
parent 788fdddf37
commit 92d6676412
2 changed files with 130 additions and 137 deletions

View file

@ -54,6 +54,15 @@ use super::recorder::{Recorder, FmtStrs};
use util::ppaux; use util::ppaux;
macro_rules! down_cast_data {
($id:ident, $kind:ident, $this:ident, $sp:expr) => {
let $id = if let super::Data::$kind(data) = $id {
data
} else {
$this.sess.span_bug($sp, &format!("unexpected data kind: {:?}", $id));
};
};
}
pub struct DumpCsvVisitor<'l, 'tcx: 'l> { pub struct DumpCsvVisitor<'l, 'tcx: 'l> {
save_ctxt: SaveContext<'l, 'tcx>, save_ctxt: SaveContext<'l, 'tcx>,
@ -436,17 +445,14 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
parent_id: NodeId) { parent_id: NodeId) {
let field_data = self.save_ctxt.get_field_data(field, parent_id); let field_data = self.save_ctxt.get_field_data(field, parent_id);
if let Some(field_data) = field_data { if let Some(field_data) = field_data {
if let super::Data::VariableData(field_data) = field_data { down_cast_data!(field_data, VariableData, self, field.span);
self.fmt.field_str(field.span, self.fmt.field_str(field.span,
Some(field_data.span), Some(field_data.span),
field_data.id, field_data.id,
&field_data.name, &field_data.name,
&field_data.qualname, &field_data.qualname,
&field_data.type_value, &field_data.type_value,
field_data.scope); field_data.scope);
} else {
self.sess.span_bug(field.span, "expected VariableData");
}
} }
} }
@ -483,19 +489,16 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
ty_params: &ast::Generics, ty_params: &ast::Generics,
body: &ast::Block) { body: &ast::Block) {
let fn_data = self.save_ctxt.get_item_data(item); let fn_data = self.save_ctxt.get_item_data(item);
if let super::Data::FunctionData(fn_data) = fn_data { down_cast_data!(fn_data, FunctionData, self, item.span);
self.fmt.fn_str(item.span, self.fmt.fn_str(item.span,
Some(fn_data.span), Some(fn_data.span),
fn_data.id, fn_data.id,
&fn_data.qualname, &fn_data.qualname,
fn_data.scope); fn_data.scope);
self.process_formals(&decl.inputs, &fn_data.qualname); self.process_formals(&decl.inputs, &fn_data.qualname);
self.process_generic_params(ty_params, item.span, &fn_data.qualname, item.id); self.process_generic_params(ty_params, item.span, &fn_data.qualname, item.id);
} else {
self.sess.span_bug(item.span, "expected FunctionData");
}
for arg in &decl.inputs { for arg in &decl.inputs {
self.visit_ty(&arg.ty); self.visit_ty(&arg.ty);
@ -514,18 +517,15 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
expr: &ast::Expr) expr: &ast::Expr)
{ {
let var_data = self.save_ctxt.get_item_data(item); let var_data = self.save_ctxt.get_item_data(item);
if let super::Data::VariableData(var_data) = var_data { down_cast_data!(var_data, VariableData, self, item.span);
self.fmt.static_str(item.span, self.fmt.static_str(item.span,
Some(var_data.span), Some(var_data.span),
var_data.id, var_data.id,
&var_data.name, &var_data.name,
&var_data.qualname, &var_data.qualname,
&var_data.value, &var_data.value,
&var_data.type_value, &var_data.type_value,
var_data.scope); var_data.scope);
} else {
self.sess.span_bug(item.span, "expected VariableData");
}
self.visit_ty(&typ); self.visit_ty(&typ);
self.visit_expr(expr); self.visit_expr(expr);
@ -591,60 +591,57 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
enum_definition: &ast::EnumDef, enum_definition: &ast::EnumDef,
ty_params: &ast::Generics) { ty_params: &ast::Generics) {
let enum_data = self.save_ctxt.get_item_data(item); let enum_data = self.save_ctxt.get_item_data(item);
if let super::Data::EnumData(enum_data) = enum_data { down_cast_data!(enum_data, EnumData, self, item.span);
self.fmt.enum_str(item.span, self.fmt.enum_str(item.span,
Some(enum_data.span), Some(enum_data.span),
enum_data.id, enum_data.id,
&enum_data.qualname, &enum_data.qualname,
enum_data.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();
qualname.push_str("::"); qualname.push_str("::");
qualname.push_str(name); qualname.push_str(name);
let val = self.span.snippet(variant.span); let val = self.span.snippet(variant.span);
match variant.node.kind { match variant.node.kind {
ast::TupleVariantKind(ref args) => { ast::TupleVariantKind(ref args) => {
// first ident in span is the variant's name // first ident in span is the variant's name
self.fmt.tuple_variant_str(variant.span, self.fmt.tuple_variant_str(variant.span,
self.span.span_for_first_ident(variant.span), self.span.span_for_first_ident(variant.span),
variant.node.id, variant.node.id,
name, name,
&qualname, &qualname,
&enum_data.qualname, &enum_data.qualname,
&val, &val,
enum_data.id); enum_data.id);
for arg in args { for arg in args {
self.visit_ty(&*arg.ty); self.visit_ty(&*arg.ty);
}
} }
ast::StructVariantKind(ref struct_def) => { }
let ctor_id = match struct_def.ctor_id { ast::StructVariantKind(ref struct_def) => {
Some(node_id) => node_id, let ctor_id = match struct_def.ctor_id {
None => -1, Some(node_id) => node_id,
}; None => -1,
self.fmt.struct_variant_str(variant.span, };
self.span.span_for_first_ident(variant.span), self.fmt.struct_variant_str(variant.span,
variant.node.id, self.span.span_for_first_ident(variant.span),
ctor_id, variant.node.id,
&qualname, ctor_id,
&enum_data.qualname, &qualname,
&val, &enum_data.qualname,
enum_data.id); &val,
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);
self.visit_ty(&*field.node.ty); self.visit_ty(&*field.node.ty);
}
} }
} }
} }
self.process_generic_params(ty_params, item.span, &enum_data.qualname, enum_data.id);
} else {
self.sess.span_bug(item.span, "expected EnumData");
} }
self.process_generic_params(ty_params, item.span, &enum_data.qualname, enum_data.id);
} }
fn process_impl(&mut self, fn process_impl(&mut self,
@ -654,37 +651,34 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
typ: &ast::Ty, typ: &ast::Ty,
impl_items: &[P<ast::ImplItem>]) { impl_items: &[P<ast::ImplItem>]) {
let impl_data = self.save_ctxt.get_item_data(item); let impl_data = self.save_ctxt.get_item_data(item);
if let super::Data::ImplData(impl_data) = impl_data { down_cast_data!(impl_data, ImplData, self, item.span);
match impl_data.self_ref { match impl_data.self_ref {
Some(ref self_ref) => { Some(ref self_ref) => {
self.fmt.ref_str(recorder::TypeRef,
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, self.fmt.ref_str(recorder::TypeRef,
item.span, item.span,
Some(trait_ref_data.span), Some(self_ref.span),
trait_ref_data.ref_id, self_ref.ref_id,
trait_ref_data.scope); self_ref.scope);
visit::walk_path(self, &trait_ref.as_ref().unwrap().path); }
None => {
self.visit_ty(&typ);
} }
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");
} }
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);
}
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);
self.process_generic_params(type_parameters, item.span, "", item.id); self.process_generic_params(type_parameters, item.span, "", item.id);
for impl_item in impl_items { for impl_item in impl_items {
@ -746,16 +740,13 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
fn process_mod(&mut self, fn process_mod(&mut self,
item: &ast::Item) { // The module in question, represented as an item. item: &ast::Item) { // The module in question, represented as an item.
let mod_data = self.save_ctxt.get_item_data(item); let mod_data = self.save_ctxt.get_item_data(item);
if let super::Data::ModData(mod_data) = mod_data { down_cast_data!(mod_data, ModData, self, item.span);
self.fmt.mod_str(item.span, self.fmt.mod_str(item.span,
Some(mod_data.span), Some(mod_data.span),
mod_data.id, mod_data.id,
&mod_data.qualname, &mod_data.qualname,
mod_data.scope, mod_data.scope,
&mod_data.filename); &mod_data.filename);
} else {
self.sess.span_bug(item.span, "expected ModData");
}
} }
fn process_path(&mut self, fn process_path(&mut self,
@ -883,16 +874,13 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
self.write_sub_paths_truncated(path, false); self.write_sub_paths_truncated(path, false);
let struct_lit_data = self.save_ctxt.get_expr_data(ex); let struct_lit_data = self.save_ctxt.get_expr_data(ex);
let struct_def = if let super::Data::TypeRefData(struct_lit_data) = struct_lit_data { down_cast_data!(struct_lit_data, TypeRefData, self, ex.span);
self.fmt.ref_str(recorder::TypeRef, self.fmt.ref_str(recorder::TypeRef,
ex.span, ex.span,
Some(struct_lit_data.span), Some(struct_lit_data.span),
struct_lit_data.ref_id, struct_lit_data.ref_id,
struct_lit_data.scope); struct_lit_data.scope);
struct_lit_data.ref_id let struct_def = struct_lit_data.ref_id;
} else {
self.sess.span_bug(ex.span, "expected TypeRefData");
};
for field in fields { for field in fields {
if generated_code(field.ident.span) { if generated_code(field.ident.span) {
@ -1269,15 +1257,12 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
self.visit_expr(&sub_ex); self.visit_expr(&sub_ex);
let field_data = self.save_ctxt.get_expr_data(ex); let field_data = self.save_ctxt.get_expr_data(ex);
if let super::Data::VariableRefData(field_data) = field_data { down_cast_data!(field_data, VariableRefData, self, ex.span);
self.fmt.ref_str(recorder::VarRef, self.fmt.ref_str(recorder::VarRef,
ex.span, ex.span,
Some(field_data.span), Some(field_data.span),
field_data.ref_id, field_data.ref_id,
field_data.scope); field_data.scope);
} else {
self.sess.span_bug(ex.span, "expected VariableRefData");
}
}, },
ast::ExprTupField(ref sub_ex, idx) => { ast::ExprTupField(ref sub_ex, idx) => {
if generated_code(sub_ex.span) { if generated_code(sub_ex.span) {

View file

@ -47,6 +47,7 @@ pub struct CrateData {
/// Data for any entity in the Rust language. The actual data contained varied /// Data for any entity in the Rust language. The actual data contained varied
/// with the kind of entity being queried. See the nested structs for details. /// with the kind of entity being queried. See the nested structs for details.
#[derive(Debug)]
pub enum Data { pub enum Data {
/// Data for all kinds of functions and methods. /// Data for all kinds of functions and methods.
FunctionData(FunctionData), FunctionData(FunctionData),
@ -67,6 +68,7 @@ pub enum Data {
} }
/// Data for all kinds of functions and methods. /// Data for all kinds of functions and methods.
#[derive(Debug)]
pub struct FunctionData { pub struct FunctionData {
pub id: NodeId, pub id: NodeId,
pub name: String, pub name: String,
@ -77,6 +79,7 @@ pub struct FunctionData {
} }
/// Data for local and global variables (consts and statics). /// Data for local and global variables (consts and statics).
#[derive(Debug)]
pub struct VariableData { pub struct VariableData {
pub id: NodeId, pub id: NodeId,
pub name: String, pub name: String,
@ -88,6 +91,7 @@ pub struct VariableData {
} }
/// Data for modules. /// Data for modules.
#[derive(Debug)]
pub struct ModData { pub struct ModData {
pub id: NodeId, pub id: NodeId,
pub name: String, pub name: String,
@ -98,6 +102,7 @@ pub struct ModData {
} }
/// Data for enum declarations. /// Data for enum declarations.
#[derive(Debug)]
pub struct EnumData { pub struct EnumData {
pub id: NodeId, pub id: NodeId,
pub value: String, pub value: String,
@ -106,6 +111,7 @@ pub struct EnumData {
pub scope: NodeId, pub scope: NodeId,
} }
#[derive(Debug)]
pub struct ImplData { pub struct ImplData {
pub id: NodeId, pub id: NodeId,
pub span: Span, pub span: Span,
@ -119,6 +125,7 @@ pub struct ImplData {
/// 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
/// will refere to that variables declaration (by ref_id)). /// will refere to that variables declaration (by ref_id)).
#[derive(Debug)]
pub struct VariableRefData { pub struct VariableRefData {
pub name: String, pub name: String,
pub span: Span, pub span: Span,
@ -127,6 +134,7 @@ pub struct VariableRefData {
} }
/// Data for a reference to a type or trait. /// Data for a reference to a type or trait.
#[derive(Debug)]
pub struct TypeRefData { pub struct TypeRefData {
pub span: Span, pub span: Span,
pub scope: NodeId, pub scope: NodeId,