save-analysis: use a macro for 'downcasting'
This commit is contained in:
parent
788fdddf37
commit
92d6676412
2 changed files with 130 additions and 137 deletions
|
@ -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) {
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Add table
Reference in a new issue