save-analysis: use a decoupled representation for dumped data

Closes #33348
This commit is contained in:
Adolfo Ochagavía 2016-05-03 12:54:29 +02:00
parent 7d8100a068
commit dca29d7b08
8 changed files with 752 additions and 838 deletions

View File

@ -10,25 +10,20 @@
use std::io::Write;
use rustc::hir::def_id::{DefId, DefIndex};
use syntax::codemap::Span;
use super::data::*;
use super::external_data::*;
use super::dump::Dump;
use super::span_utils::SpanUtils;
pub struct CsvDumper<'tcx, 'b, W: 'b> {
output: &'b mut W,
span: SpanUtils<'tcx>
pub struct CsvDumper<'b, W: 'b> {
output: &'b mut W
}
impl<'a, 'b, W: Write> CsvDumper<'a, 'b, W> {
pub fn new(writer: &'b mut W, span: SpanUtils<'a>) -> CsvDumper<'a, 'b, W> {
CsvDumper { output: writer, span: span }
impl<'b, W: Write> CsvDumper<'b, W> {
pub fn new(writer: &'b mut W) -> CsvDumper<'b, W> {
CsvDumper { output: writer }
}
fn record(&mut self, kind: &str, span: Span, values: String) {
let span_str = self.span.extent_str(span);
fn record(&mut self, kind: &str, span: SpanData, values: String) {
let span_str = span_extent_str(span);
if let Err(_) = write!(self.output, "{},{}{}\n", kind, span_str, values) {
error!("Error writing output");
}
@ -41,7 +36,7 @@ impl<'a, 'b, W: Write> CsvDumper<'a, 'b, W> {
}
}
impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> {
impl<'b, W: Write + 'b> Dump for CsvDumper<'b, W> {
fn crate_prelude(&mut self, data: CratePreludeData) {
let values = make_values_str(&[
("name", &data.crate_name),
@ -93,21 +88,14 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> {
}
fn impl_data(&mut self, data: ImplData) {
let self_ref = data.self_ref.unwrap_or(null_def_id());
let trait_ref = data.trait_ref.unwrap_or(null_def_id());
let id = data.id.to_string();
let ref_id = self_ref.index.as_usize().to_string();
let ref_id_crate = self_ref.krate.to_string();
let trait_id = trait_ref.index.as_usize().to_string();
let trait_id_crate = trait_ref.krate.to_string();
let ref_id = data.self_ref.unwrap_or(Id::null()).to_string();
let trait_id = data.trait_ref.unwrap_or(Id::null()).to_string();
let scope = data.scope.to_string();
let values = make_values_str(&[
("id", &id),
("refid", &ref_id),
("refidcrate", &ref_id_crate),
("traitid", &trait_id),
("traitidcrate", &trait_id_crate),
("scopeid", &scope)
]);
@ -115,33 +103,24 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> {
}
fn inheritance(&mut self, data: InheritanceData) {
let base_id = data.base_id.index.as_usize().to_string();
let base_crate = data.base_id.krate.to_string();
let deriv_id = data.deriv_id.to_string();
let deriv_crate = 0.to_string();
let values = make_values_str(&[
("base", &base_id),
("basecrate", &base_crate),
("derived", &deriv_id),
("derivedcrate", &deriv_crate)
]);
let base_id = data.base_id.to_string();
let deriv_id = data.deriv_id.to_string();
let values = make_values_str(&[
("base", &base_id),
("derived", &deriv_id),
]);
self.record("inheritance", data.span, values);
}
fn function(&mut self, data: FunctionData) {
let (decl_id, decl_crate) = match data.declaration {
Some(id) => (id.index.as_usize().to_string(), id.krate.to_string()),
None => (String::new(), String::new())
};
let id = data.id.to_string();
let decl_id = data.declaration.unwrap_or(Id::null()).to_string();
let scope = data.scope.to_string();
let values = make_values_str(&[
("id", &id),
("qualname", &data.qualname),
("declid", &decl_id),
("declidcrate", &decl_crate),
("scopeid", &scope)
]);
@ -149,12 +128,10 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> {
}
fn function_ref(&mut self, data: FunctionRefData) {
let ref_id = data.ref_id.index.as_usize().to_string();
let ref_crate = data.ref_id.krate.to_string();
let ref_id = data.ref_id.to_string();
let scope = data.scope.to_string();
let values = make_values_str(&[
("refid", &ref_id),
("refidcrate", &ref_crate),
("qualname", ""),
("scopeid", &scope)
]);
@ -163,13 +140,11 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> {
}
fn function_call(&mut self, data: FunctionCallData) {
let ref_id = data.ref_id.index.as_usize().to_string();
let ref_crate = data.ref_id.krate.to_string();
let ref_id = data.ref_id.to_string();
let qualname = String::new();
let scope = data.scope.to_string();
let values = make_values_str(&[
("refid", &ref_id),
("refidcrate", &ref_crate),
("qualname", &qualname),
("scopeid", &scope)
]);
@ -190,21 +165,12 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> {
}
fn method_call(&mut self, data: MethodCallData) {
let (dcn, dck) = match data.decl_id {
Some(declid) => (declid.index.as_usize().to_string(), declid.krate.to_string()),
None => (String::new(), String::new()),
};
let ref_id = data.ref_id.unwrap_or(null_def_id());
let def_id = ref_id.index.as_usize().to_string();
let def_crate = ref_id.krate.to_string();
let decl_id = data.decl_id.unwrap_or(Id::null()).to_string();
let ref_id = data.ref_id.unwrap_or(Id::null()).to_string();
let scope = data.scope.to_string();
let values = make_values_str(&[
("refid", &def_id),
("refidcrate", &def_crate),
("declid", &dcn),
("declidcrate", &dck),
("refid", &ref_id),
("declid", &decl_id),
("scopeid", &scope)
]);
@ -245,15 +211,11 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> {
}
fn mod_ref(&mut self, data: ModRefData) {
let (ref_id, ref_crate) = match data.ref_id {
Some(rid) => (rid.index.as_usize().to_string(), rid.krate.to_string()),
None => (0.to_string(), 0.to_string())
};
let ref_id = data.ref_id.unwrap_or(Id::null()).to_string();
let scope = data.scope.to_string();
let values = make_values_str(&[
("refid", &ref_id),
("refidcrate", &ref_crate),
("qualname", &data.qualname),
("scopeid", &scope)
]);
@ -320,15 +282,10 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> {
}
fn type_ref(&mut self, data: TypeRefData) {
let (ref_id, ref_crate) = match data.ref_id {
Some(id) => (id.index.as_usize().to_string(), id.krate.to_string()),
None => (0.to_string(), 0.to_string())
};
let ref_id = data.ref_id.unwrap_or(Id::null()).to_string();
let scope = data.scope.to_string();
let values = make_values_str(&[
("refid", &ref_id),
("refidcrate", &ref_crate),
("qualname", &data.qualname),
("scopeid", &scope)
]);
@ -348,16 +305,12 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> {
}
fn use_data(&mut self, data: UseData) {
let mod_id = data.mod_id.unwrap_or(null_def_id());
let id = data.id.to_string();
let ref_id = mod_id.index.as_usize().to_string();
let ref_crate = mod_id.krate.to_string();
let mod_id = data.mod_id.unwrap_or(Id::null()).to_string();
let scope = data.scope.to_string();
let values = make_values_str(&[
("id", &id),
("refid", &ref_id),
("refidcrate", &ref_crate),
("mod_id", &mod_id),
("name", &data.name),
("scopeid", &scope)
]);
@ -395,12 +348,10 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> {
}
fn variable_ref(&mut self, data: VariableRefData) {
let ref_id = data.ref_id.index.as_usize().to_string();
let ref_crate = data.ref_id.krate.to_string();
let id = data.ref_id.to_string();
let scope = data.scope.to_string();
let values = make_values_str(&[
("refid", &ref_id),
("refidcrate", &ref_crate),
("id", &id),
("qualname", ""),
("scopeid", &scope)
]);
@ -431,9 +382,9 @@ fn make_values_str(pairs: &[(&'static str, &str)]) -> String {
})
}
fn null_def_id() -> DefId {
DefId {
krate: 0,
index: DefIndex::new(0),
}
fn span_extent_str(span: SpanData) -> String {
format!("file_name,\"{}\",file_line,{},file_col,{},byte_start,{}\
file_line_end,{},file_col_end,{},byte_end,{}",
span.file_name, span.line_start, span.column_start, span.byte_start,
span.line_end, span.column_end, span.byte_end)
}

View File

@ -16,39 +16,8 @@
use std::hash::Hasher;
use rustc::hir::def_id::DefId;
use rustc::ty;
use syntax::ast::{CrateNum, NodeId};
use syntax::codemap::{Span, CodeMap};
#[derive(Debug, Clone, RustcEncodable)]
pub struct SpanData {
file_name: String,
byte_start: u32,
byte_end: u32,
/// 1-based.
line_start: usize,
line_end: usize,
/// 1-based, character offset.
column_start: usize,
column_end: usize,
}
impl SpanData {
pub fn from_span(span: Span, cm: &CodeMap) -> SpanData {
let start = cm.lookup_char_pos(span.lo);
let end = cm.lookup_char_pos(span.hi);
SpanData {
file_name: start.file.name.clone(),
byte_start: span.lo.0,
byte_end: span.hi.0,
line_start: start.line,
line_end: end.line,
column_start: start.col.0 + 1,
column_end: end.col.0 + 1,
}
}
}
use syntax::codemap::Span;
pub struct CrateData {
pub name: String,
@ -359,58 +328,3 @@ pub struct VariableRefData {
pub scope: NodeId,
pub ref_id: DefId,
}
// Emitted ids are used to cross-reference items across crates. DefIds and
// NodeIds do not usually correspond in any way. The strategy is to use the
// index from the DefId as a crate-local id. However, within a crate, DefId
// indices and NodeIds can overlap. So, we must adjust the NodeIds. If an
// item can be identified by a DefId as well as a NodeId, then we use the
// DefId index as the id. If it can't, then we have to use the NodeId, but
// need to adjust it so it will not clash with any possible DefId index.
pub fn normalize_node_id<'a>(tcx: &ty::TyCtxt<'a>, id: NodeId) -> usize {
match tcx.map.opt_local_def_id(id) {
Some(id) => id.index.as_usize(),
None => id as usize + tcx.map.num_local_def_ids()
}
}
// Macro to implement a normalize() function (see below for usage)
macro_rules! impl_normalize {
($($t:ty => $($field:ident),*);*) => {
$(
impl $t {
pub fn normalize<'a>(mut self, tcx: &ty::TyCtxt<'a>) -> $t {
$(
self.$field = normalize_node_id(tcx, self.$field) as u32;
)*
self
}
}
)*
}
}
impl_normalize! {
EnumData => id, scope;
ExternCrateData => id, scope;
FunctionCallData => scope;
FunctionData => id, scope;
FunctionRefData => scope;
ImplData => id, scope;
InheritanceData => deriv_id;
MacroUseData => scope;
MethodCallData => scope;
MethodData => id, scope;
ModData => id, scope;
ModRefData => scope;
StructData => ctor_id, id, scope;
StructVariantData => id, scope;
TupleVariantData => id, scope;
TraitData => id, scope;
TypedefData => id;
TypeRefData => scope;
UseData => id, scope;
UseGlobData => id, scope;
VariableData => id;
VariableRefData => scope
}

View File

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use super::data::*;
use super::external_data::*;
pub trait Dump {
fn crate_prelude(&mut self, CratePreludeData) {}

View File

@ -45,6 +45,7 @@ use syntax::ptr::P;
use super::{escape, generated_code, SaveContext, PathCollector};
use super::data::*;
use super::dump::Dump;
use super::external_data::Lower;
use super::span_utils::SpanUtils;
use super::recorder;
@ -133,7 +134,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
span: krate.span,
};
self.dumper.crate_prelude(data);
self.dumper.crate_prelude(data.lower(self.tcx));
}
// Return all non-empty prefixes of a path.
@ -203,7 +204,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
qualname: qualname,
scope: self.cur_scope,
ref_id: None
}.normalize(&self.tcx));
}.lower(self.tcx));
}
}
@ -228,7 +229,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
qualname: qualname,
scope: self.cur_scope,
ref_id: None
}.normalize(&self.tcx));
}.lower(self.tcx));
}
}
@ -249,7 +250,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
span: *span,
qualname: qualname.to_owned(),
scope: 0
});
}.lower(self.tcx));
// write the other sub-paths
if len <= 2 {
@ -262,7 +263,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
qualname: qualname.to_owned(),
scope: self.cur_scope,
ref_id: None
}.normalize(&self.tcx));
}.lower(self.tcx));
}
}
@ -304,7 +305,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
ref_id: Some(def_id),
scope: scope,
qualname: String::new()
}.normalize(&self.tcx));
}.lower(self.tcx));
}
Def::Struct(..) |
Def::Enum(..) |
@ -316,7 +317,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
ref_id: Some(def_id),
scope: scope,
qualname: String::new()
}.normalize(&self.tcx));
}.lower(self.tcx));
}
Def::Static(_, _) |
Def::Const(_) |
@ -329,14 +330,14 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
ref_id: def_id,
scope: scope,
name: String::new()
}.normalize(&self.tcx));
}.lower(self.tcx));
}
Def::Fn(..) => {
self.dumper.function_ref(FunctionRefData {
span: sub_span.expect("No span found for fn ref"),
ref_id: def_id,
scope: scope
}.normalize(&self.tcx));
}.lower(self.tcx));
}
Def::SelfTy(..) |
Def::Label(_) |
@ -371,7 +372,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
type_value: typ,
value: String::new(),
scope: 0
}.normalize(&self.tcx));
}.lower(self.tcx));
}
}
}
@ -389,7 +390,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
if body.is_some() {
if !self.span.filter_generated(Some(method_data.span), span) {
self.dumper.function(method_data.clone().normalize(&self.tcx));
self.dumper.function(method_data.clone().lower(self.tcx));
}
self.process_formals(&sig.decl.inputs, &method_data.qualname);
} else {
@ -399,7 +400,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
span: method_data.span,
scope: method_data.scope,
qualname: method_data.qualname.clone(),
}.normalize(&self.tcx));
}.lower(self.tcx));
}
}
self.process_generic_params(&sig.generics, span, &method_data.qualname, id);
@ -424,7 +425,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
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 {
if !self.span.filter_generated(Some(trait_ref_data.span), trait_ref.path.span) {
self.dumper.type_ref(trait_ref_data.normalize(&self.tcx));
self.dumper.type_ref(trait_ref_data.lower(self.tcx));
}
visit::walk_path(self, &trait_ref.path);
@ -435,9 +436,8 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
let field_data = self.save_ctxt.get_field_data(field, parent_id);
if let Some(mut field_data) = field_data {
if !self.span.filter_generated(Some(field_data.span), field.span) {
field_data.scope = normalize_node_id(&self.tcx, field_data.scope) as u32;
field_data.value = String::new();
self.dumper.variable(field_data.normalize(&self.tcx));
self.dumper.variable(field_data.lower(self.tcx));
}
}
}
@ -466,7 +466,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
id: param.id,
qualname: name,
value: String::new()
}.normalize(&self.tcx));
}.lower(self.tcx));
}
}
self.visit_generics(generics);
@ -480,7 +480,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
if let Some(fn_data) = self.save_ctxt.get_item_data(item) {
down_cast_data!(fn_data, FunctionData, item.span);
if !self.span.filter_generated(Some(fn_data.span), item.span) {
self.dumper.function(fn_data.clone().normalize(&self.tcx));
self.dumper.function(fn_data.clone().lower(self.tcx));
}
self.process_formals(&decl.inputs, &fn_data.qualname);
@ -502,9 +502,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
if let Some(var_data) = self.save_ctxt.get_item_data(item) {
down_cast_data!(var_data, VariableData, item.span);
if !self.span.filter_generated(Some(var_data.span), item.span) {
let mut var_data = var_data;
var_data.scope = normalize_node_id(&self.tcx, var_data.scope) as u32;
self.dumper.variable(var_data.normalize(&self.tcx));
self.dumper.variable(var_data.lower(self.tcx));
}
}
self.visit_ty(&typ);
@ -529,8 +527,8 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
qualname: qualname,
value: self.span.snippet(expr.span),
type_value: ty_to_string(&typ),
scope: normalize_node_id(&self.tcx, self.cur_scope) as u32
}.normalize(&self.tcx));
scope: self.cur_scope
}.lower(self.tcx));
}
// walk type and init value
@ -554,7 +552,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
qualname: qualname.clone(),
scope: self.cur_scope,
value: val
}.normalize(&self.tcx));
}.lower(self.tcx));
}
@ -577,9 +575,8 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
Some(data) => data,
};
down_cast_data!(enum_data, EnumData, item.span);
let normalized = enum_data.clone().normalize(&self.tcx);
if !self.span.filter_generated(Some(normalized.span), item.span) {
self.dumper.enum_data(normalized);
if !self.span.filter_generated(Some(enum_data.span), item.span) {
self.dumper.enum_data(enum_data.clone().lower(self.tcx));
}
for variant in &enum_definition.variants {
@ -600,7 +597,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
type_value: enum_data.qualname.clone(),
value: val,
scope: enum_data.scope
}.normalize(&self.tcx));
}.lower(self.tcx));
}
}
_ => {
@ -614,7 +611,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
type_value: enum_data.qualname.clone(),
value: val,
scope: enum_data.scope
}.normalize(&self.tcx));
}.lower(self.tcx));
}
}
}
@ -640,12 +637,12 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
if let Some(ref self_ref) = impl_data.self_ref {
has_self_ref = true;
if !self.span.filter_generated(Some(self_ref.span), item.span) {
self.dumper.type_ref(self_ref.clone().normalize(&self.tcx));
self.dumper.type_ref(self_ref.clone().lower(self.tcx));
}
}
if let Some(ref trait_ref_data) = impl_data.trait_ref {
if !self.span.filter_generated(Some(trait_ref_data.span), item.span) {
self.dumper.type_ref(trait_ref_data.clone().normalize(&self.tcx));
self.dumper.type_ref(trait_ref_data.clone().lower(self.tcx));
}
visit::walk_path(self, &trait_ref.as_ref().unwrap().path);
@ -658,7 +655,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
scope: impl_data.scope,
trait_ref: impl_data.trait_ref.map(|d| d.ref_id.unwrap()),
self_ref: impl_data.self_ref.map(|d| d.ref_id.unwrap())
}.normalize(&self.tcx));
}.lower(self.tcx));
}
}
if !has_self_ref {
@ -685,7 +682,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
qualname: qualname.clone(),
scope: self.cur_scope,
value: val
}.normalize(&self.tcx));
}.lower(self.tcx));
}
// super-traits
@ -708,7 +705,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
ref_id: Some(id),
scope: self.cur_scope,
qualname: String::new()
}.normalize(&self.tcx));
}.lower(self.tcx));
}
if !self.span.filter_generated(sub_span, trait_ref.path.span) {
@ -717,7 +714,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
span: sub_span,
base_id: id,
deriv_id: item.id
}.normalize(&self.tcx));
}.lower(self.tcx));
}
}
}
@ -734,7 +731,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
if let Some(mod_data) = self.save_ctxt.get_item_data(item) {
down_cast_data!(mod_data, ModData, item.span);
if !self.span.filter_generated(Some(mod_data.span), item.span) {
self.dumper.mod_data(mod_data.normalize(&self.tcx));
self.dumper.mod_data(mod_data.lower(self.tcx));
}
}
}
@ -765,14 +762,14 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
ref_id: Some(vrd.ref_id),
scope: vrd.scope,
qualname: String::new()
}.normalize(&self.tcx));
}.lower(self.tcx));
}
Some(recorder::FnRef) => {
self.dumper.function_ref(FunctionRefData {
span: vrd.span,
ref_id: vrd.ref_id,
scope: vrd.scope
}.normalize(&self.tcx));
}.lower(self.tcx));
}
Some(recorder::ModRef) => {
self.dumper.mod_ref( ModRefData {
@ -780,27 +777,27 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
ref_id: Some(vrd.ref_id),
scope: vrd.scope,
qualname: String::new()
}.normalize(&self.tcx));
}.lower(self.tcx));
}
Some(recorder::VarRef) | None
=> self.dumper.variable_ref(vrd.normalize(&self.tcx))
=> self.dumper.variable_ref(vrd.lower(self.tcx))
}
}
}
Data::TypeRefData(trd) => {
if !self.span.filter_generated(Some(trd.span), path.span) {
self.dumper.type_ref(trd.normalize(&self.tcx));
self.dumper.type_ref(trd.lower(self.tcx));
}
}
Data::MethodCallData(mcd) => {
if !self.span.filter_generated(Some(mcd.span), path.span) {
self.dumper.method_call(mcd.normalize(&self.tcx));
self.dumper.method_call(mcd.lower(self.tcx));
}
}
Data::FunctionCallData(fcd) => {
if !self.span.filter_generated(Some(fcd.span), path.span) {
self.dumper.function_call(fcd.normalize(&self.tcx));
self.dumper.function_call(fcd.lower(self.tcx));
}
}
_ => {
@ -842,7 +839,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
if let Some(struct_lit_data) = self.save_ctxt.get_expr_data(ex) {
down_cast_data!(struct_lit_data, TypeRefData, ex.span);
if !self.span.filter_generated(Some(struct_lit_data.span), ex.span) {
self.dumper.type_ref(struct_lit_data.normalize(&self.tcx));
self.dumper.type_ref(struct_lit_data.lower(self.tcx));
}
let scope = self.save_ctxt.enclosing_scope(ex.id);
@ -852,7 +849,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
.get_field_ref_data(field, variant, scope) {
if !self.span.filter_generated(Some(field_data.span), field.ident.span) {
self.dumper.variable_ref(field_data.normalize(&self.tcx));
self.dumper.variable_ref(field_data.lower(self.tcx));
}
}
@ -867,7 +864,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
if let Some(mcd) = self.save_ctxt.get_expr_data(ex) {
down_cast_data!(mcd, MethodCallData, ex.span);
if !self.span.filter_generated(Some(mcd.span), ex.span) {
self.dumper.method_call(mcd.normalize(&self.tcx));
self.dumper.method_call(mcd.lower(self.tcx));
}
}
@ -892,7 +889,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
ref_id: f.did,
scope: self.cur_scope,
name: String::new()
}.normalize(&self.tcx));
}.lower(self.tcx));
}
}
self.visit_pat(&field.pat);
@ -931,7 +928,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
value: value,
type_value: typ,
scope: 0
}.normalize(&self.tcx));
}.lower(self.tcx));
}
}
}
@ -961,7 +958,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
span: sub_span,
name: data.name.clone(),
qualname: qualname.clone()
});
}.lower(self.tcx));
}
}
if !self.mac_uses.contains(&data.span) {
@ -974,7 +971,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
scope: data.scope,
callee_span: data.callee_span,
imported: data.imported
}.normalize(&self.tcx));
}.lower(self.tcx));
}
}
}
@ -1014,7 +1011,7 @@ impl<'v, 'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'v> for DumpVisitor<'l, 'tcx,
mod_id: mod_id,
name: ident.to_string(),
scope: self.cur_scope
}.normalize(&self.tcx));
}.lower(self.tcx));
}
self.write_sub_paths_truncated(path, true);
}
@ -1037,7 +1034,7 @@ impl<'v, 'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'v> for DumpVisitor<'l, 'tcx,
id: item.id,
names: names,
scope: self.cur_scope
}.normalize(&self.tcx));
}.lower(self.tcx));
}
self.write_sub_paths(path, true);
}
@ -1081,7 +1078,7 @@ impl<'v, 'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'v> for DumpVisitor<'l, 'tcx,
location: location,
span: alias_span.expect("No span found for extern crate"),
scope: self.cur_scope,
}.normalize(&self.tcx));
}.lower(self.tcx));
}
}
Fn(ref decl, _, _, _, ref ty_params, ref body) =>
@ -1115,7 +1112,7 @@ impl<'v, 'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'v> for DumpVisitor<'l, 'tcx,
id: item.id,
qualname: qualname.clone(),
value: value
}.normalize(&self.tcx));
}.lower(self.tcx));
}
self.visit_ty(&ty);
@ -1195,7 +1192,7 @@ impl<'v, 'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'v> for DumpVisitor<'l, 'tcx,
ref_id: Some(id),
scope: self.cur_scope,
qualname: String::new()
}.normalize(&self.tcx));
}.lower(self.tcx));
}
}
@ -1232,7 +1229,7 @@ impl<'v, 'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'v> for DumpVisitor<'l, 'tcx,
if let Some(field_data) = self.save_ctxt.get_expr_data(ex) {
down_cast_data!(field_data, VariableRefData, ex.span);
if !self.span.filter_generated(Some(field_data.span), ex.span) {
self.dumper.variable_ref(field_data.normalize(&self.tcx));
self.dumper.variable_ref(field_data.lower(self.tcx));
}
}
}
@ -1250,7 +1247,7 @@ impl<'v, 'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'v> for DumpVisitor<'l, 'tcx,
ref_id: def.struct_variant().fields[idx.node].did,
scope: self.cur_scope,
name: String::new()
}.normalize(&self.tcx));
}.lower(self.tcx));
}
}
ty::TyTuple(_) => {}
@ -1343,7 +1340,7 @@ impl<'v, 'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'v> for DumpVisitor<'l, 'tcx,
value: value,
type_value: String::new(),
scope: 0
}.normalize(&self.tcx));
}.lower(self.tcx));
}
}
Def::Variant(..) | Def::Enum(..) |

View File

@ -0,0 +1,640 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::fmt::{self, Display, Formatter};
use rustc::hir::def_id::DefId;
use rustc::hir::map::Map;
use rustc::ty::TyCtxt;
use syntax::ast::{CrateNum, NodeId};
use syntax::codemap::{Span, CodeMap};
use super::data;
// FIXME: this should be pub(crate), but the current snapshot doesn't allow it yet
pub trait Lower {
type Target;
fn lower(self, tcx: &TyCtxt) -> Self::Target;
}
// We use a newtype to enforce conversion of all NodeIds (which are u32s as well)
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable)]
pub struct Id(u32);
impl Id {
pub fn from_def_id(id: DefId) -> Id {
Id(id.index.as_u32())
}
// FIXME: this function is called with non-local NodeIds. This means that they
// cannot be mapped to a DefId. We should remove those calls. In the meantime,
// we return a "null Id" when the NodeId is invalid.
pub fn from_node_id(id: NodeId, map: &Map) -> Id {
map.opt_local_def_id(id).map(|id| Id(id.index.as_u32()))
.unwrap_or(Id::null())
}
pub fn null() -> Id {
Id(u32::max_value())
}
}
impl Display for Id {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
self.0.fmt(f)
}
}
#[derive(Clone, Debug, RustcEncodable)]
pub struct SpanData {
pub file_name: String,
pub byte_start: u32,
pub byte_end: u32,
/// 1-based.
pub line_start: usize,
pub line_end: usize,
/// 1-based, character offset.
pub column_start: usize,
pub column_end: usize,
}
impl SpanData {
pub fn from_span(span: Span, cm: &CodeMap) -> SpanData {
let start = cm.lookup_char_pos(span.lo);
let end = cm.lookup_char_pos(span.hi);
SpanData {
file_name: start.file.name.clone(),
byte_start: span.lo.0,
byte_end: span.hi.0,
line_start: start.line,
line_end: end.line,
column_start: start.col.0 + 1,
column_end: end.col.0 + 1,
}
}
}
#[derive(Debug, RustcEncodable)]
pub struct CratePreludeData {
pub crate_name: String,
pub crate_root: String,
pub external_crates: Vec<data::ExternalCrateData>,
pub span: SpanData,
}
impl Lower for data::CratePreludeData {
type Target = CratePreludeData;
fn lower(self, tcx: &TyCtxt) -> CratePreludeData {
CratePreludeData {
crate_name: self.crate_name,
crate_root: self.crate_root,
external_crates: self.external_crates,
span: SpanData::from_span(self.span, tcx.sess.codemap()),
}
}
}
/// Data for enum declarations.
#[derive(Clone, Debug, RustcEncodable)]
pub struct EnumData {
pub id: Id,
pub value: String,
pub qualname: String,
pub span: SpanData,
pub scope: Id,
}
impl Lower for data::EnumData {
type Target = EnumData;
fn lower(self, tcx: &TyCtxt) -> EnumData {
EnumData {
id: Id::from_node_id(self.id, &tcx.map),
value: self.value,
qualname: self.qualname,
span: SpanData::from_span(self.span, tcx.sess.codemap()),
scope: Id::from_node_id(self.scope, &tcx.map),
}
}
}
/// Data for extern crates.
#[derive(Debug, RustcEncodable)]
pub struct ExternCrateData {
pub id: Id,
pub name: String,
pub crate_num: CrateNum,
pub location: String,
pub span: SpanData,
pub scope: Id,
}
impl Lower for data::ExternCrateData {
type Target = ExternCrateData;
fn lower(self, tcx: &TyCtxt) -> ExternCrateData {
ExternCrateData {
id: Id::from_node_id(self.id, &tcx.map),
name: self.name,
crate_num: self.crate_num,
location: self.location,
span: SpanData::from_span(self.span, tcx.sess.codemap()),
scope: Id::from_node_id(self.scope, &tcx.map),
}
}
}
/// Data about a function call.
#[derive(Debug, RustcEncodable)]
pub struct FunctionCallData {
pub span: SpanData,
pub scope: Id,
pub ref_id: Id,
}
impl Lower for data::FunctionCallData {
type Target = FunctionCallData;
fn lower(self, tcx: &TyCtxt) -> FunctionCallData {
FunctionCallData {
span: SpanData::from_span(self.span, tcx.sess.codemap()),
scope: Id::from_node_id(self.scope, &tcx.map),
ref_id: Id::from_def_id(self.ref_id),
}
}
}
/// Data for all kinds of functions and methods.
#[derive(Clone, Debug, RustcEncodable)]
pub struct FunctionData {
pub id: Id,
pub name: String,
pub qualname: String,
pub declaration: Option<Id>,
pub span: SpanData,
pub scope: Id,
}
impl Lower for data::FunctionData {
type Target = FunctionData;
fn lower(self, tcx: &TyCtxt) -> FunctionData {
FunctionData {
id: Id::from_node_id(self.id, &tcx.map),
name: self.name,
qualname: self.qualname,
declaration: self.declaration.map(Id::from_def_id),
span: SpanData::from_span(self.span, tcx.sess.codemap()),
scope: Id::from_node_id(self.scope, &tcx.map),
}
}
}
/// Data about a function call.
#[derive(Debug, RustcEncodable)]
pub struct FunctionRefData {
pub span: SpanData,
pub scope: Id,
pub ref_id: Id,
}
impl Lower for data::FunctionRefData {
type Target = FunctionRefData;
fn lower(self, tcx: &TyCtxt) -> FunctionRefData {
FunctionRefData {
span: SpanData::from_span(self.span, tcx.sess.codemap()),
scope: Id::from_node_id(self.scope, &tcx.map),
ref_id: Id::from_def_id(self.ref_id),
}
}
}
#[derive(Debug, RustcEncodable)]
pub struct ImplData {
pub id: Id,
pub span: SpanData,
pub scope: Id,
pub trait_ref: Option<Id>,
pub self_ref: Option<Id>,
}
impl Lower for data::ImplData {
type Target = ImplData;
fn lower(self, tcx: &TyCtxt) -> ImplData {
ImplData {
id: Id::from_node_id(self.id, &tcx.map),
span: SpanData::from_span(self.span, tcx.sess.codemap()),
scope: Id::from_node_id(self.scope, &tcx.map),
trait_ref: self.trait_ref.map(Id::from_def_id),
self_ref: self.self_ref.map(Id::from_def_id),
}
}
}
#[derive(Debug, RustcEncodable)]
pub struct InheritanceData {
pub span: SpanData,
pub base_id: Id,
pub deriv_id: Id
}
impl Lower for data::InheritanceData {
type Target = InheritanceData;
fn lower(self, tcx: &TyCtxt) -> InheritanceData {
InheritanceData {
span: SpanData::from_span(self.span, tcx.sess.codemap()),
base_id: Id::from_def_id(self.base_id),
deriv_id: Id::from_node_id(self.deriv_id, &tcx.map)
}
}
}
/// Data about a macro declaration.
#[derive(Debug, RustcEncodable)]
pub struct MacroData {
pub span: SpanData,
pub name: String,
pub qualname: String,
}
impl Lower for data::MacroData {
type Target = MacroData;
fn lower(self, tcx: &TyCtxt) -> MacroData {
MacroData {
span: SpanData::from_span(self.span, tcx.sess.codemap()),
name: self.name,
qualname: self.qualname,
}
}
}
/// Data about a macro use.
#[derive(Debug, RustcEncodable)]
pub struct MacroUseData {
pub span: SpanData,
pub name: String,
pub qualname: String,
// Because macro expansion happens before ref-ids are determined,
// we use the callee span to reference the associated macro definition.
pub callee_span: SpanData,
pub scope: Id,
pub imported: bool,
}
impl Lower for data::MacroUseData {
type Target = MacroUseData;
fn lower(self, tcx: &TyCtxt) -> MacroUseData {
MacroUseData {
span: SpanData::from_span(self.span, tcx.sess.codemap()),
name: self.name,
qualname: self.qualname,
callee_span: SpanData::from_span(self.callee_span, tcx.sess.codemap()),
scope: Id::from_node_id(self.scope, &tcx.map),
imported: self.imported,
}
}
}
/// Data about a method call.
#[derive(Debug, RustcEncodable)]
pub struct MethodCallData {
pub span: SpanData,
pub scope: Id,
pub ref_id: Option<Id>,
pub decl_id: Option<Id>,
}
impl Lower for data::MethodCallData {
type Target = MethodCallData;
fn lower(self, tcx: &TyCtxt) -> MethodCallData {
MethodCallData {
span: SpanData::from_span(self.span, tcx.sess.codemap()),
scope: Id::from_node_id(self.scope, &tcx.map),
ref_id: self.ref_id.map(Id::from_def_id),
decl_id: self.decl_id.map(Id::from_def_id),
}
}
}
/// Data for method declarations (methods with a body are treated as functions).
#[derive(Clone, Debug, RustcEncodable)]
pub struct MethodData {
pub id: Id,
pub qualname: String,
pub span: SpanData,
pub scope: Id,
}
impl Lower for data::MethodData {
type Target = MethodData;
fn lower(self, tcx: &TyCtxt) -> MethodData {
MethodData {
span: SpanData::from_span(self.span, tcx.sess.codemap()),
scope: Id::from_node_id(self.scope, &tcx.map),
id: Id::from_node_id(self.id, &tcx.map),
qualname: self.qualname,
}
}
}
/// Data for modules.
#[derive(Debug, RustcEncodable)]
pub struct ModData {
pub id: Id,
pub name: String,
pub qualname: String,
pub span: SpanData,
pub scope: Id,
pub filename: String,
}
impl Lower for data::ModData {
type Target = ModData;
fn lower(self, tcx: &TyCtxt) -> ModData {
ModData {
id: Id::from_node_id(self.id, &tcx.map),
name: self.name,
qualname: self.qualname,
span: SpanData::from_span(self.span, tcx.sess.codemap()),
scope: Id::from_node_id(self.scope, &tcx.map),
filename: self.filename,
}
}
}
/// Data for a reference to a module.
#[derive(Debug, RustcEncodable)]
pub struct ModRefData {
pub span: SpanData,
pub scope: Id,
pub ref_id: Option<Id>,
pub qualname: String
}
impl Lower for data::ModRefData {
type Target = ModRefData;
fn lower(self, tcx: &TyCtxt) -> ModRefData {
ModRefData {
span: SpanData::from_span(self.span, tcx.sess.codemap()),
scope: Id::from_node_id(self.scope, &tcx.map),
ref_id: self.ref_id.map(Id::from_def_id),
qualname: self.qualname,
}
}
}
#[derive(Debug, RustcEncodable)]
pub struct StructData {
pub span: SpanData,
pub id: Id,
pub ctor_id: Id,
pub qualname: String,
pub scope: Id,
pub value: String
}
impl Lower for data::StructData {
type Target = StructData;
fn lower(self, tcx: &TyCtxt) -> StructData {
StructData {
span: SpanData::from_span(self.span, tcx.sess.codemap()),
id: Id::from_node_id(self.id, &tcx.map),
ctor_id: Id::from_node_id(self.ctor_id, &tcx.map),
qualname: self.qualname,
scope: Id::from_node_id(self.scope, &tcx.map),
value: self.value
}
}
}
#[derive(Debug, RustcEncodable)]
pub struct StructVariantData {
pub span: SpanData,
pub id: Id,
pub qualname: String,
pub type_value: String,
pub value: String,
pub scope: Id
}
impl Lower for data::StructVariantData {
type Target = StructVariantData;
fn lower(self, tcx: &TyCtxt) -> StructVariantData {
StructVariantData {
span: SpanData::from_span(self.span, tcx.sess.codemap()),
id: Id::from_node_id(self.id, &tcx.map),
qualname: self.qualname,
type_value: self.type_value,
value: self.value,
scope: Id::from_node_id(self.scope, &tcx.map),
}
}
}
#[derive(Debug, RustcEncodable)]
pub struct TraitData {
pub span: SpanData,
pub id: Id,
pub qualname: String,
pub scope: Id,
pub value: String
}
impl Lower for data::TraitData {
type Target = TraitData;
fn lower(self, tcx: &TyCtxt) -> TraitData {
TraitData {
span: SpanData::from_span(self.span, tcx.sess.codemap()),
id: Id::from_node_id(self.id, &tcx.map),
qualname: self.qualname,
scope: Id::from_node_id(self.scope, &tcx.map),
value: self.value,
}
}
}
#[derive(Debug, RustcEncodable)]
pub struct TupleVariantData {
pub span: SpanData,
pub id: Id,
pub name: String,
pub qualname: String,
pub type_value: String,
pub value: String,
pub scope: Id,
}
impl Lower for data::TupleVariantData {
type Target = TupleVariantData;
fn lower(self, tcx: &TyCtxt) -> TupleVariantData {
TupleVariantData {
span: SpanData::from_span(self.span, tcx.sess.codemap()),
id: Id::from_node_id(self.id, &tcx.map),
name: self.name,
qualname: self.qualname,
type_value: self.type_value,
value: self.value,
scope: Id::from_node_id(self.scope, &tcx.map),
}
}
}
/// Data for a typedef.
#[derive(Debug, RustcEncodable)]
pub struct TypedefData {
pub id: Id,
pub span: SpanData,
pub qualname: String,
pub value: String,
}
impl Lower for data::TypedefData {
type Target = TypedefData;
fn lower(self, tcx: &TyCtxt) -> TypedefData {
TypedefData {
id: Id::from_node_id(self.id, &tcx.map),
span: SpanData::from_span(self.span, tcx.sess.codemap()),
qualname: self.qualname,
value: self.value,
}
}
}
/// Data for a reference to a type or trait.
#[derive(Clone, Debug, RustcEncodable)]
pub struct TypeRefData {
pub span: SpanData,
pub scope: Id,
pub ref_id: Option<Id>,
pub qualname: String,
}
impl Lower for data::TypeRefData {
type Target = TypeRefData;
fn lower(self, tcx: &TyCtxt) -> TypeRefData {
TypeRefData {
span: SpanData::from_span(self.span, tcx.sess.codemap()),
scope: Id::from_node_id(self.scope, &tcx.map),
ref_id: self.ref_id.map(Id::from_def_id),
qualname: self.qualname,
}
}
}
#[derive(Debug, RustcEncodable)]
pub struct UseData {
pub id: Id,
pub span: SpanData,
pub name: String,
pub mod_id: Option<Id>,
pub scope: Id
}
impl Lower for data::UseData {
type Target = UseData;
fn lower(self, tcx: &TyCtxt) -> UseData {
UseData {
id: Id::from_node_id(self.id, &tcx.map),
span: SpanData::from_span(self.span, tcx.sess.codemap()),
name: self.name,
mod_id: self.mod_id.map(Id::from_def_id),
scope: Id::from_node_id(self.scope, &tcx.map),
}
}
}
#[derive(Debug, RustcEncodable)]
pub struct UseGlobData {
pub id: Id,
pub span: SpanData,
pub names: Vec<String>,
pub scope: Id
}
impl Lower for data::UseGlobData {
type Target = UseGlobData;
fn lower(self, tcx: &TyCtxt) -> UseGlobData {
UseGlobData {
id: Id::from_node_id(self.id, &tcx.map),
span: SpanData::from_span(self.span, tcx.sess.codemap()),
names: self.names,
scope: Id::from_node_id(self.scope, &tcx.map),
}
}
}
/// Data for local and global variables (consts and statics).
#[derive(Debug, RustcEncodable)]
pub struct VariableData {
pub id: Id,
pub name: String,
pub qualname: String,
pub span: SpanData,
pub scope: Id,
pub value: String,
pub type_value: String,
}
impl Lower for data::VariableData {
type Target = VariableData;
fn lower(self, tcx: &TyCtxt) -> VariableData {
VariableData {
id: Id::from_node_id(self.id, &tcx.map),
name: self.name,
qualname: self.qualname,
span: SpanData::from_span(self.span, tcx.sess.codemap()),
scope: Id::from_node_id(self.scope, &tcx.map),
value: self.value,
type_value: self.type_value,
}
}
}
/// Data for the use of some item (e.g., the use of a local variable, which
/// will refer to that variables declaration (by ref_id)).
#[derive(Debug, RustcEncodable)]
pub struct VariableRefData {
pub name: String,
pub span: SpanData,
pub scope: Id,
pub ref_id: Id,
}
impl Lower for data::VariableRefData {
type Target = VariableRefData;
fn lower(self, tcx: &TyCtxt) -> VariableRefData {
VariableRefData {
name: self.name,
span: SpanData::from_span(self.span, tcx.sess.codemap()),
scope: Id::from_node_id(self.scope, &tcx.map),
ref_id: Id::from_def_id(self.ref_id),
}
}
}

View File

@ -11,29 +11,25 @@
use std::io::Write;
use rustc_serialize::json::as_json;
use syntax::codemap::CodeMap;
use syntax::ast::CrateNum;
use super::data::{self, SpanData};
use super::external_data::*;
use super::dump::Dump;
pub struct JsonDumper<'a, 'b, W: Write + 'b> {
pub struct JsonDumper<'b, W: Write + 'b> {
output: &'b mut W,
codemap: &'a CodeMap,
first: bool,
}
impl<'a, 'b, W: Write> JsonDumper<'a, 'b, W> {
pub fn new(writer: &'b mut W, codemap: &'a CodeMap) -> JsonDumper<'a, 'b, W> {
impl<'b, W: Write> JsonDumper<'b, W> {
pub fn new(writer: &'b mut W) -> JsonDumper<'b, W> {
if let Err(_) = write!(writer, "[") {
error!("Error writing output");
}
JsonDumper { output: writer, codemap:codemap, first: true }
JsonDumper { output: writer, first: true }
}
}
impl<'a, 'b, W: Write> Drop for JsonDumper<'a, 'b, W> {
impl<'b, W: Write> Drop for JsonDumper<'b, W> {
fn drop(&mut self) {
if let Err(_) = write!(self.output, "]") {
error!("Error writing output");
@ -43,7 +39,7 @@ impl<'a, 'b, W: Write> Drop for JsonDumper<'a, 'b, W> {
macro_rules! impl_fn {
($fn_name: ident, $data_type: ident) => {
fn $fn_name(&mut self, data: data::$data_type) {
fn $fn_name(&mut self, data: $data_type) {
if self.first {
self.first = false;
} else {
@ -51,7 +47,6 @@ macro_rules! impl_fn {
error!("Error writing output");
}
}
let data = data.lower(self.codemap);
if let Err(_) = write!(self.output, "{}", as_json(&data)) {
error!("Error writing output '{}'", as_json(&data));
}
@ -59,7 +54,7 @@ macro_rules! impl_fn {
}
}
impl<'a, 'b, W: Write + 'b> Dump for JsonDumper<'a, 'b, W> {
impl<'b, W: Write + 'b> Dump for JsonDumper<'b, W> {
impl_fn!(crate_prelude, CratePreludeData);
impl_fn!(enum_data, EnumData);
impl_fn!(extern_crate, ExternCrateData);
@ -85,567 +80,3 @@ impl<'a, 'b, W: Write + 'b> Dump for JsonDumper<'a, 'b, W> {
impl_fn!(variable, VariableData);
impl_fn!(variable_ref, VariableRefData);
}
trait Lower {
type Target;
fn lower(self, cm: &CodeMap) -> Self::Target;
}
pub type Id = u32;
#[derive(Debug, RustcEncodable)]
pub struct CratePreludeData {
pub crate_name: String,
pub crate_root: String,
pub external_crates: Vec<data::ExternalCrateData>,
pub span: SpanData,
}
impl Lower for data::CratePreludeData {
type Target = CratePreludeData;
fn lower(self, cm: &CodeMap) -> CratePreludeData {
CratePreludeData {
crate_name: self.crate_name,
crate_root: self.crate_root,
external_crates: self.external_crates,
span: SpanData::from_span(self.span, cm),
}
}
}
/// Data for enum declarations.
#[derive(Clone, Debug, RustcEncodable)]
pub struct EnumData {
pub id: Id,
pub value: String,
pub qualname: String,
pub span: SpanData,
pub scope: Id,
}
impl Lower for data::EnumData {
type Target = EnumData;
fn lower(self, cm: &CodeMap) -> EnumData {
EnumData {
id: self.id,
value: self.value,
qualname: self.qualname,
span: SpanData::from_span(self.span, cm),
scope: self.scope,
}
}
}
/// Data for extern crates.
#[derive(Debug, RustcEncodable)]
pub struct ExternCrateData {
pub id: Id,
pub name: String,
pub crate_num: CrateNum,
pub location: String,
pub span: SpanData,
pub scope: Id,
}
impl Lower for data::ExternCrateData {
type Target = ExternCrateData;
fn lower(self, cm: &CodeMap) -> ExternCrateData {
ExternCrateData {
id: self.id,
name: self.name,
crate_num: self.crate_num,
location: self.location,
span: SpanData::from_span(self.span, cm),
scope: self.scope,
}
}
}
/// Data about a function call.
#[derive(Debug, RustcEncodable)]
pub struct FunctionCallData {
pub span: SpanData,
pub scope: Id,
pub ref_id: Id,
}
impl Lower for data::FunctionCallData {
type Target = FunctionCallData;
fn lower(self, cm: &CodeMap) -> FunctionCallData {
FunctionCallData {
span: SpanData::from_span(self.span, cm),
scope: self.scope,
ref_id: self.ref_id.index.as_u32(),
}
}
}
/// Data for all kinds of functions and methods.
#[derive(Clone, Debug, RustcEncodable)]
pub struct FunctionData {
pub id: Id,
pub name: String,
pub qualname: String,
pub declaration: Option<Id>,
pub span: SpanData,
pub scope: Id,
}
impl Lower for data::FunctionData {
type Target = FunctionData;
fn lower(self, cm: &CodeMap) -> FunctionData {
FunctionData {
id: self.id,
name: self.name,
qualname: self.qualname,
declaration: self.declaration.map(|id| id.index.as_u32()),
span: SpanData::from_span(self.span, cm),
scope: self.scope,
}
}
}
/// Data about a function call.
#[derive(Debug, RustcEncodable)]
pub struct FunctionRefData {
pub span: SpanData,
pub scope: Id,
pub ref_id: Id,
}
impl Lower for data::FunctionRefData {
type Target = FunctionRefData;
fn lower(self, cm: &CodeMap) -> FunctionRefData {
FunctionRefData {
span: SpanData::from_span(self.span, cm),
scope: self.scope,
ref_id: self.ref_id.index.as_u32(),
}
}
}
#[derive(Debug, RustcEncodable)]
pub struct ImplData {
pub id: Id,
pub span: SpanData,
pub scope: Id,
pub trait_ref: Option<Id>,
pub self_ref: Option<Id>,
}
impl Lower for data::ImplData {
type Target = ImplData;
fn lower(self, cm: &CodeMap) -> ImplData {
ImplData {
id: self.id,
span: SpanData::from_span(self.span, cm),
scope: self.scope,
trait_ref: self.trait_ref.map(|id| id.index.as_u32()),
self_ref: self.self_ref.map(|id| id.index.as_u32()),
}
}
}
#[derive(Debug, RustcEncodable)]
pub struct InheritanceData {
pub span: SpanData,
pub base_id: Id,
pub deriv_id: Id
}
impl Lower for data::InheritanceData {
type Target = InheritanceData;
fn lower(self, cm: &CodeMap) -> InheritanceData {
InheritanceData {
span: SpanData::from_span(self.span, cm),
base_id: self.base_id.index.as_u32(),
deriv_id: self.deriv_id
}
}
}
/// Data about a macro declaration.
#[derive(Debug, RustcEncodable)]
pub struct MacroData {
pub span: SpanData,
pub name: String,
pub qualname: String,
}
impl Lower for data::MacroData {
type Target = MacroData;
fn lower(self, cm: &CodeMap) -> MacroData {
MacroData {
span: SpanData::from_span(self.span, cm),
name: self.name,
qualname: self.qualname,
}
}
}
/// Data about a macro use.
#[derive(Debug, RustcEncodable)]
pub struct MacroUseData {
pub span: SpanData,
pub name: String,
pub qualname: String,
// Because macro expansion happens before ref-ids are determined,
// we use the callee span to reference the associated macro definition.
pub callee_span: SpanData,
pub scope: Id,
pub imported: bool,
}
impl Lower for data::MacroUseData {
type Target = MacroUseData;
fn lower(self, cm: &CodeMap) -> MacroUseData {
MacroUseData {
span: SpanData::from_span(self.span, cm),
name: self.name,
qualname: self.qualname,
callee_span: SpanData::from_span(self.callee_span, cm),
scope: self.scope,
imported: self.imported,
}
}
}
/// Data about a method call.
#[derive(Debug, RustcEncodable)]
pub struct MethodCallData {
pub span: SpanData,
pub scope: Id,
pub ref_id: Option<Id>,
pub decl_id: Option<Id>,
}
impl Lower for data::MethodCallData {
type Target = MethodCallData;
fn lower(self, cm: &CodeMap) -> MethodCallData {
MethodCallData {
span: SpanData::from_span(self.span, cm),
scope: self.scope,
ref_id: self.ref_id.map(|id| id.index.as_u32()),
decl_id: self.decl_id.map(|id| id.index.as_u32()),
}
}
}
/// Data for method declarations (methods with a body are treated as functions).
#[derive(Clone, Debug, RustcEncodable)]
pub struct MethodData {
pub id: Id,
pub qualname: String,
pub span: SpanData,
pub scope: Id,
}
impl Lower for data::MethodData {
type Target = MethodData;
fn lower(self, cm: &CodeMap) -> MethodData {
MethodData {
span: SpanData::from_span(self.span, cm),
scope: self.scope,
id: self.id,
qualname: self.qualname,
}
}
}
/// Data for modules.
#[derive(Debug, RustcEncodable)]
pub struct ModData {
pub id: Id,
pub name: String,
pub qualname: String,
pub span: SpanData,
pub scope: Id,
pub filename: String,
}
impl Lower for data::ModData {
type Target = ModData;
fn lower(self, cm: &CodeMap) -> ModData {
ModData {
id: self.id,
name: self.name,
qualname: self.qualname,
span: SpanData::from_span(self.span, cm),
scope: self.scope,
filename: self.filename,
}
}
}
/// Data for a reference to a module.
#[derive(Debug, RustcEncodable)]
pub struct ModRefData {
pub span: SpanData,
pub scope: Id,
pub ref_id: Option<Id>,
pub qualname: String
}
impl Lower for data::ModRefData {
type Target = ModRefData;
fn lower(self, cm: &CodeMap) -> ModRefData {
ModRefData {
span: SpanData::from_span(self.span, cm),
scope: self.scope,
ref_id: self.ref_id.map(|id| id.index.as_u32()),
qualname: self.qualname,
}
}
}
#[derive(Debug, RustcEncodable)]
pub struct StructData {
pub span: SpanData,
pub id: Id,
pub ctor_id: Id,
pub qualname: String,
pub scope: Id,
pub value: String
}
impl Lower for data::StructData {
type Target = StructData;
fn lower(self, cm: &CodeMap) -> StructData {
StructData {
span: SpanData::from_span(self.span, cm),
id: self.id,
ctor_id: self.ctor_id,
qualname: self.qualname,
scope: self.scope,
value: self.value
}
}
}
#[derive(Debug, RustcEncodable)]
pub struct StructVariantData {
pub span: SpanData,
pub id: Id,
pub qualname: String,
pub type_value: String,
pub value: String,
pub scope: Id
}
impl Lower for data::StructVariantData {
type Target = StructVariantData;
fn lower(self, cm: &CodeMap) -> StructVariantData {
StructVariantData {
span: SpanData::from_span(self.span, cm),
id: self.id,
qualname: self.qualname,
type_value: self.type_value,
value: self.value,
scope: self.scope,
}
}
}
#[derive(Debug, RustcEncodable)]
pub struct TraitData {
pub span: SpanData,
pub id: Id,
pub qualname: String,
pub scope: Id,
pub value: String
}
impl Lower for data::TraitData {
type Target = TraitData;
fn lower(self, cm: &CodeMap) -> TraitData {
TraitData {
span: SpanData::from_span(self.span, cm),
id: self.id,
qualname: self.qualname,
scope: self.scope,
value: self.value,
}
}
}
#[derive(Debug, RustcEncodable)]
pub struct TupleVariantData {
pub span: SpanData,
pub id: Id,
pub name: String,
pub qualname: String,
pub type_value: String,
pub value: String,
pub scope: Id,
}
impl Lower for data::TupleVariantData {
type Target = TupleVariantData;
fn lower(self, cm: &CodeMap) -> TupleVariantData {
TupleVariantData {
span: SpanData::from_span(self.span, cm),
id: self.id,
name: self.name,
qualname: self.qualname,
type_value: self.type_value,
value: self.value,
scope: self.scope,
}
}
}
/// Data for a typedef.
#[derive(Debug, RustcEncodable)]
pub struct TypedefData {
pub id: Id,
pub span: SpanData,
pub qualname: String,
pub value: String,
}
impl Lower for data::TypedefData {
type Target = TypedefData;
fn lower(self, cm: &CodeMap) -> TypedefData {
TypedefData {
id: self.id,
span: SpanData::from_span(self.span, cm),
qualname: self.qualname,
value: self.value,
}
}
}
/// Data for a reference to a type or trait.
#[derive(Clone, Debug, RustcEncodable)]
pub struct TypeRefData {
pub span: SpanData,
pub scope: Id,
pub ref_id: Option<Id>,
pub qualname: String,
}
impl Lower for data::TypeRefData {
type Target = TypeRefData;
fn lower(self, cm: &CodeMap) -> TypeRefData {
TypeRefData {
span: SpanData::from_span(self.span, cm),
scope: self.scope,
ref_id: self.ref_id.map(|id| id.index.as_u32()),
qualname: self.qualname,
}
}
}
#[derive(Debug, RustcEncodable)]
pub struct UseData {
pub id: Id,
pub span: SpanData,
pub name: String,
pub mod_id: Option<Id>,
pub scope: Id
}
impl Lower for data::UseData {
type Target = UseData;
fn lower(self, cm: &CodeMap) -> UseData {
UseData {
id: self.id,
span: SpanData::from_span(self.span, cm),
name: self.name,
mod_id: self.mod_id.map(|id| id.index.as_u32()),
scope: self.scope,
}
}
}
#[derive(Debug, RustcEncodable)]
pub struct UseGlobData {
pub id: Id,
pub span: SpanData,
pub names: Vec<String>,
pub scope: Id
}
impl Lower for data::UseGlobData {
type Target = UseGlobData;
fn lower(self, cm: &CodeMap) -> UseGlobData {
UseGlobData {
id: self.id,
span: SpanData::from_span(self.span, cm),
names: self.names,
scope: self.scope,
}
}
}
/// Data for local and global variables (consts and statics).
#[derive(Debug, RustcEncodable)]
pub struct VariableData {
pub id: Id,
pub name: String,
pub qualname: String,
pub span: SpanData,
pub scope: Id,
pub value: String,
pub type_value: String,
}
impl Lower for data::VariableData {
type Target = VariableData;
fn lower(self, cm: &CodeMap) -> VariableData {
VariableData {
id: self.id,
name: self.name,
qualname: self.qualname,
span: SpanData::from_span(self.span, cm),
scope: self.scope,
value: self.value,
type_value: self.type_value,
}
}
}
/// Data for the use of some item (e.g., the use of a local variable, which
/// will refer to that variables declaration (by ref_id)).
#[derive(Debug, RustcEncodable)]
pub struct VariableRefData {
pub name: String,
pub span: SpanData,
pub scope: Id,
pub ref_id: Id,
}
impl Lower for data::VariableRefData {
type Target = VariableRefData;
fn lower(self, cm: &CodeMap) -> VariableRefData {
VariableRefData {
name: self.name,
span: SpanData::from_span(self.span, cm),
scope: self.scope,
ref_id: self.ref_id.index.as_u32(),
}
}
}

View File

@ -28,6 +28,15 @@
#[macro_use] extern crate syntax;
extern crate serialize as rustc_serialize;
mod csv_dumper;
mod json_dumper;
mod data;
mod dump;
mod dump_visitor;
pub mod external_data;
#[macro_use]
pub mod span_utils;
use rustc::hir;
use rustc::hir::map::NodeItem;
use rustc::hir::def::Def;
@ -45,14 +54,6 @@ use syntax::parse::token::{self, keywords};
use syntax::visit::{self, Visitor};
use syntax::print::pprust::ty_to_string;
mod csv_dumper;
mod json_dumper;
mod data;
mod dump;
mod dump_visitor;
#[macro_use]
pub mod span_utils;
pub use self::csv_dumper::CsvDumper;
pub use self::json_dumper::JsonDumper;
pub use self::data::*;
@ -748,7 +749,6 @@ pub fn process_crate<'l, 'tcx>(tcx: &'l TyCtxt<'tcx>,
root_path.pop();
let output = &mut output_file;
let utils: SpanUtils<'tcx> = SpanUtils::new(&tcx.sess);
let save_ctxt = SaveContext::new(tcx);
macro_rules! dump {
@ -762,8 +762,8 @@ pub fn process_crate<'l, 'tcx>(tcx: &'l TyCtxt<'tcx>,
}
match format {
Format::Csv => dump!(CsvDumper::new(output, utils)),
Format::Json => dump!(JsonDumper::new(output, utils.sess.codemap())),
Format::Csv => dump!(CsvDumper::new(output)),
Format::Json => dump!(JsonDumper::new(output)),
}
}

View File

@ -18,10 +18,8 @@ use std::path::Path;
use syntax::ast;
use syntax::codemap::*;
use syntax::parse::lexer;
use syntax::parse::lexer::{Reader, StringReader};
use syntax::parse::token;
use syntax::parse::token::{keywords, Token};
use syntax::parse::lexer::{self, Reader, StringReader};
use syntax::parse::token::{self, keywords, Token};
#[derive(Clone)]
pub struct SpanUtils<'a> {
@ -48,23 +46,6 @@ impl<'a> SpanUtils<'a> {
}
}
// Standard string for extents/location.
#[rustfmt_skip]
pub fn extent_str(&self, span: Span) -> String {
let lo_loc = self.sess.codemap().lookup_char_pos(span.lo);
let hi_loc = self.sess.codemap().lookup_char_pos(span.hi);
let lo_pos = self.sess.codemap().bytepos_to_file_charpos(span.lo);
let hi_pos = self.sess.codemap().bytepos_to_file_charpos(span.hi);
let lo_pos_byte = self.sess.codemap().lookup_byte_offset(span.lo).pos;
let hi_pos_byte = self.sess.codemap().lookup_byte_offset(span.hi).pos;
format!("file_name,\"{}\",file_line,{},file_col,{},extent_start,{},extent_start_bytes,{},\
file_line_end,{},file_col_end,{},extent_end,{},extent_end_bytes,{}",
SpanUtils::make_path_string(&lo_loc.file.name),
lo_loc.line, lo_loc.col.to_usize(), lo_pos.to_usize(), lo_pos_byte.to_usize(),
hi_loc.line, hi_loc.col.to_usize(), hi_pos.to_usize(), hi_pos_byte.to_usize())
}
// sub_span starts at span.lo, so we need to adjust the positions etc.
// If sub_span is None, we don't need to adjust.
pub fn make_sub_span(&self, span: Span, sub_span: Option<Span>) -> Option<Span> {