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;
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> {
save_ctxt: SaveContext<'l, 'tcx>,
@ -436,17 +445,14 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
parent_id: NodeId) {
let field_data = self.save_ctxt.get_field_data(field, parent_id);
if let Some(field_data) = field_data {
if let super::Data::VariableData(field_data) = field_data {
self.fmt.field_str(field.span,
Some(field_data.span),
field_data.id,
&field_data.name,
&field_data.qualname,
&field_data.type_value,
field_data.scope);
} else {
self.sess.span_bug(field.span, "expected VariableData");
}
down_cast_data!(field_data, VariableData, self, field.span);
self.fmt.field_str(field.span,
Some(field_data.span),
field_data.id,
&field_data.name,
&field_data.qualname,
&field_data.type_value,
field_data.scope);
}
}
@ -483,19 +489,16 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
ty_params: &ast::Generics,
body: &ast::Block) {
let fn_data = self.save_ctxt.get_item_data(item);
if let super::Data::FunctionData(fn_data) = fn_data {
self.fmt.fn_str(item.span,
Some(fn_data.span),
fn_data.id,
&fn_data.qualname,
fn_data.scope);
down_cast_data!(fn_data, FunctionData, self, item.span);
self.fmt.fn_str(item.span,
Some(fn_data.span),
fn_data.id,
&fn_data.qualname,
fn_data.scope);
self.process_formals(&decl.inputs, &fn_data.qualname);
self.process_generic_params(ty_params, item.span, &fn_data.qualname, item.id);
} else {
self.sess.span_bug(item.span, "expected FunctionData");
}
self.process_formals(&decl.inputs, &fn_data.qualname);
self.process_generic_params(ty_params, item.span, &fn_data.qualname, item.id);
for arg in &decl.inputs {
self.visit_ty(&arg.ty);
@ -514,18 +517,15 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
expr: &ast::Expr)
{
let var_data = self.save_ctxt.get_item_data(item);
if let super::Data::VariableData(var_data) = var_data {
self.fmt.static_str(item.span,
Some(var_data.span),
var_data.id,
&var_data.name,
&var_data.qualname,
&var_data.value,
&var_data.type_value,
var_data.scope);
} else {
self.sess.span_bug(item.span, "expected VariableData");
}
down_cast_data!(var_data, VariableData, self, item.span);
self.fmt.static_str(item.span,
Some(var_data.span),
var_data.id,
&var_data.name,
&var_data.qualname,
&var_data.value,
&var_data.type_value,
var_data.scope);
self.visit_ty(&typ);
self.visit_expr(expr);
@ -591,60 +591,57 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
enum_definition: &ast::EnumDef,
ty_params: &ast::Generics) {
let enum_data = self.save_ctxt.get_item_data(item);
if let super::Data::EnumData(enum_data) = enum_data {
self.fmt.enum_str(item.span,
Some(enum_data.span),
enum_data.id,
&enum_data.qualname,
enum_data.scope,
&enum_data.value);
down_cast_data!(enum_data, EnumData, self, item.span);
self.fmt.enum_str(item.span,
Some(enum_data.span),
enum_data.id,
&enum_data.qualname,
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();
qualname.push_str("::");
qualname.push_str(name);
let val = self.span.snippet(variant.span);
match variant.node.kind {
ast::TupleVariantKind(ref args) => {
// first ident in span is the variant's name
self.fmt.tuple_variant_str(variant.span,
self.span.span_for_first_ident(variant.span),
variant.node.id,
name,
&qualname,
&enum_data.qualname,
&val,
enum_data.id);
for arg in args {
self.visit_ty(&*arg.ty);
}
for variant in &enum_definition.variants {
let name = &get_ident(variant.node.name);
let mut qualname = enum_data.qualname.clone();
qualname.push_str("::");
qualname.push_str(name);
let val = self.span.snippet(variant.span);
match variant.node.kind {
ast::TupleVariantKind(ref args) => {
// first ident in span is the variant's name
self.fmt.tuple_variant_str(variant.span,
self.span.span_for_first_ident(variant.span),
variant.node.id,
name,
&qualname,
&enum_data.qualname,
&val,
enum_data.id);
for arg in args {
self.visit_ty(&*arg.ty);
}
ast::StructVariantKind(ref struct_def) => {
let ctor_id = match struct_def.ctor_id {
Some(node_id) => node_id,
None => -1,
};
self.fmt.struct_variant_str(variant.span,
self.span.span_for_first_ident(variant.span),
variant.node.id,
ctor_id,
&qualname,
&enum_data.qualname,
&val,
enum_data.id);
}
ast::StructVariantKind(ref struct_def) => {
let ctor_id = match struct_def.ctor_id {
Some(node_id) => node_id,
None => -1,
};
self.fmt.struct_variant_str(variant.span,
self.span.span_for_first_ident(variant.span),
variant.node.id,
ctor_id,
&qualname,
&enum_data.qualname,
&val,
enum_data.id);
for field in &struct_def.fields {
self.process_struct_field_def(field, variant.node.id);
self.visit_ty(&*field.node.ty);
}
for field in &struct_def.fields {
self.process_struct_field_def(field, variant.node.id);
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,
@ -654,37 +651,34 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
typ: &ast::Ty,
impl_items: &[P<ast::ImplItem>]) {
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,
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 {
down_cast_data!(impl_data, ImplData, self, item.span);
match impl_data.self_ref {
Some(ref self_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);
Some(self_ref.span),
self_ref.ref_id,
self_ref.scope);
}
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);
for impl_item in impl_items {
@ -746,16 +740,13 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
fn process_mod(&mut self,
item: &ast::Item) { // The module in question, represented as an item.
let mod_data = self.save_ctxt.get_item_data(item);
if let super::Data::ModData(mod_data) = mod_data {
self.fmt.mod_str(item.span,
Some(mod_data.span),
mod_data.id,
&mod_data.qualname,
mod_data.scope,
&mod_data.filename);
} else {
self.sess.span_bug(item.span, "expected ModData");
}
down_cast_data!(mod_data, ModData, self, item.span);
self.fmt.mod_str(item.span,
Some(mod_data.span),
mod_data.id,
&mod_data.qualname,
mod_data.scope,
&mod_data.filename);
}
fn process_path(&mut self,
@ -883,16 +874,13 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
self.write_sub_paths_truncated(path, false);
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 {
self.fmt.ref_str(recorder::TypeRef,
ex.span,
Some(struct_lit_data.span),
struct_lit_data.ref_id,
struct_lit_data.scope);
struct_lit_data.ref_id
} else {
self.sess.span_bug(ex.span, "expected TypeRefData");
};
down_cast_data!(struct_lit_data, TypeRefData, self, ex.span);
self.fmt.ref_str(recorder::TypeRef,
ex.span,
Some(struct_lit_data.span),
struct_lit_data.ref_id,
struct_lit_data.scope);
let struct_def = struct_lit_data.ref_id;
for field in fields {
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);
let field_data = self.save_ctxt.get_expr_data(ex);
if let super::Data::VariableRefData(field_data) = field_data {
self.fmt.ref_str(recorder::VarRef,
ex.span,
Some(field_data.span),
field_data.ref_id,
field_data.scope);
} else {
self.sess.span_bug(ex.span, "expected VariableRefData");
}
down_cast_data!(field_data, VariableRefData, self, ex.span);
self.fmt.ref_str(recorder::VarRef,
ex.span,
Some(field_data.span),
field_data.ref_id,
field_data.scope);
},
ast::ExprTupField(ref sub_ex, idx) => {
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
/// with the kind of entity being queried. See the nested structs for details.
#[derive(Debug)]
pub enum Data {
/// Data for all kinds of functions and methods.
FunctionData(FunctionData),
@ -67,6 +68,7 @@ pub enum Data {
}
/// Data for all kinds of functions and methods.
#[derive(Debug)]
pub struct FunctionData {
pub id: NodeId,
pub name: String,
@ -77,6 +79,7 @@ pub struct FunctionData {
}
/// Data for local and global variables (consts and statics).
#[derive(Debug)]
pub struct VariableData {
pub id: NodeId,
pub name: String,
@ -88,6 +91,7 @@ pub struct VariableData {
}
/// Data for modules.
#[derive(Debug)]
pub struct ModData {
pub id: NodeId,
pub name: String,
@ -98,6 +102,7 @@ pub struct ModData {
}
/// Data for enum declarations.
#[derive(Debug)]
pub struct EnumData {
pub id: NodeId,
pub value: String,
@ -106,6 +111,7 @@ pub struct EnumData {
pub scope: NodeId,
}
#[derive(Debug)]
pub struct ImplData {
pub id: NodeId,
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
/// will refere to that variables declaration (by ref_id)).
#[derive(Debug)]
pub struct VariableRefData {
pub name: String,
pub span: Span,
@ -127,6 +134,7 @@ pub struct VariableRefData {
}
/// Data for a reference to a type or trait.
#[derive(Debug)]
pub struct TypeRefData {
pub span: Span,
pub scope: NodeId,