Auto merge of #33208 - nrc:save-json, r=pnkfelix
save-analysis: dump in JSON format cc #18582
This commit is contained in:
commit
4751e45521
@ -120,7 +120,7 @@ DEPS_rustc_trans := arena flate getopts graphviz libc rustc rustc_back rustc_mir
|
||||
log syntax serialize rustc_llvm rustc_platform_intrinsics \
|
||||
rustc_const_math rustc_const_eval rustc_incremental
|
||||
DEPS_rustc_incremental := rbml rustc serialize rustc_data_structures
|
||||
DEPS_rustc_save_analysis := rustc log syntax
|
||||
DEPS_rustc_save_analysis := rustc log syntax serialize
|
||||
DEPS_rustc_typeck := rustc syntax rustc_platform_intrinsics rustc_const_math \
|
||||
rustc_const_eval
|
||||
|
||||
|
@ -618,7 +618,9 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
|
||||
ls: bool = (false, parse_bool,
|
||||
"list the symbols defined by a library crate"),
|
||||
save_analysis: bool = (false, parse_bool,
|
||||
"write syntax and type analysis information in addition to normal output"),
|
||||
"write syntax and type analysis (in JSON format) information in addition to normal output"),
|
||||
save_analysis_csv: bool = (false, parse_bool,
|
||||
"write syntax and type analysis (in CSV format) information in addition to normal output"),
|
||||
print_move_fragments: bool = (false, parse_bool,
|
||||
"print out move-fragment data for every fn"),
|
||||
flowgraph_print_loans: bool = (false, parse_bool,
|
||||
|
@ -141,8 +141,7 @@ pub fn compile_input(sess: &Session,
|
||||
dep_graph));
|
||||
|
||||
// Discard MTWT tables that aren't required past lowering to HIR.
|
||||
if !sess.opts.debugging_opts.keep_mtwt_tables &&
|
||||
!sess.opts.debugging_opts.save_analysis {
|
||||
if !keep_mtwt_tables(sess) {
|
||||
syntax::ext::mtwt::clear_tables();
|
||||
}
|
||||
|
||||
@ -179,8 +178,7 @@ pub fn compile_input(sess: &Session,
|
||||
"early lint checks",
|
||||
|| lint::check_ast_crate(sess, &expanded_crate));
|
||||
|
||||
let opt_crate = if sess.opts.debugging_opts.keep_ast ||
|
||||
sess.opts.debugging_opts.save_analysis {
|
||||
let opt_crate = if keep_ast(sess) {
|
||||
Some(&expanded_crate)
|
||||
} else {
|
||||
drop(expanded_crate);
|
||||
@ -249,6 +247,18 @@ pub fn compile_input(sess: &Session,
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn keep_mtwt_tables(sess: &Session) -> bool {
|
||||
sess.opts.debugging_opts.keep_mtwt_tables ||
|
||||
sess.opts.debugging_opts.save_analysis ||
|
||||
sess.opts.debugging_opts.save_analysis_csv
|
||||
}
|
||||
|
||||
fn keep_ast(sess: &Session) -> bool {
|
||||
sess.opts.debugging_opts.keep_ast ||
|
||||
sess.opts.debugging_opts.save_analysis ||
|
||||
sess.opts.debugging_opts.save_analysis_csv
|
||||
}
|
||||
|
||||
/// The name used for source code that doesn't originate in a file
|
||||
/// (e.g. source from stdin or a string)
|
||||
pub fn anon_src() -> String {
|
||||
|
@ -483,7 +483,7 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls {
|
||||
control.after_llvm.stop = Compilation::Stop;
|
||||
}
|
||||
|
||||
if sess.opts.debugging_opts.save_analysis {
|
||||
if save_analysis(sess) {
|
||||
control.after_analysis.callback = box |state| {
|
||||
time(state.session.time_passes(), "save analysis", || {
|
||||
save::process_crate(state.tcx.unwrap(),
|
||||
@ -491,7 +491,8 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls {
|
||||
state.krate.unwrap(),
|
||||
state.analysis.unwrap(),
|
||||
state.crate_name.unwrap(),
|
||||
state.out_dir)
|
||||
state.out_dir,
|
||||
save_analysis_format(state.session))
|
||||
});
|
||||
};
|
||||
control.after_analysis.run_callback_on_error = true;
|
||||
@ -502,6 +503,21 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls {
|
||||
}
|
||||
}
|
||||
|
||||
fn save_analysis(sess: &Session) -> bool {
|
||||
sess.opts.debugging_opts.save_analysis ||
|
||||
sess.opts.debugging_opts.save_analysis_csv
|
||||
}
|
||||
|
||||
fn save_analysis_format(sess: &Session) -> save::Format {
|
||||
if sess.opts.debugging_opts.save_analysis {
|
||||
save::Format::Json
|
||||
} else if sess.opts.debugging_opts.save_analysis_csv {
|
||||
save::Format::Csv
|
||||
} else {
|
||||
unreachable!();
|
||||
}
|
||||
}
|
||||
|
||||
impl RustcDefaultCalls {
|
||||
pub fn list_metadata(sess: &Session, matches: &getopts::Matches, input: &Input) -> Compilation {
|
||||
let r = matches.opt_strs("Z");
|
||||
|
@ -12,3 +12,4 @@ crate-type = ["dylib"]
|
||||
log = { path = "../liblog" }
|
||||
rustc = { path = "../librustc" }
|
||||
syntax = { path = "../libsyntax" }
|
||||
serialize = { path = "../libserialize" }
|
||||
|
@ -19,13 +19,12 @@ use super::span_utils::SpanUtils;
|
||||
|
||||
pub struct CsvDumper<'tcx, 'b, W: 'b> {
|
||||
output: &'b mut W,
|
||||
dump_spans: bool,
|
||||
span: SpanUtils<'tcx>
|
||||
}
|
||||
|
||||
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, dump_spans: false, span: span }
|
||||
CsvDumper { output: writer, span: span }
|
||||
}
|
||||
|
||||
fn record(&mut self, kind: &str, span: Span, values: String) {
|
||||
@ -40,36 +39,23 @@ impl<'a, 'b, W: Write> CsvDumper<'a, 'b, W> {
|
||||
error!("Error writing output '{}'", info);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dump_span(&mut self, kind: &str, span: Span) {
|
||||
assert!(self.dump_spans);
|
||||
let result = format!("span,kind,{},{},text,\"{}\"\n",
|
||||
kind,
|
||||
self.span.extent_str(span),
|
||||
escape(self.span.snippet(span)));
|
||||
self.record_raw(&result);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> {
|
||||
fn crate_prelude(&mut self, span: Span, data: CratePreludeData) {
|
||||
let crate_root = data.crate_root.unwrap_or("<no source>".to_owned());
|
||||
|
||||
fn crate_prelude(&mut self, data: CratePreludeData) {
|
||||
let values = make_values_str(&[
|
||||
("name", &data.crate_name),
|
||||
("crate_root", &crate_root)
|
||||
("crate_root", &data.crate_root)
|
||||
]);
|
||||
|
||||
self.record("crate", span, values);
|
||||
self.record("crate", data.span, values);
|
||||
|
||||
for c in data.external_crates {
|
||||
let num = c.num.to_string();
|
||||
let lo_loc = self.span.sess.codemap().lookup_char_pos(span.lo);
|
||||
let file_name = SpanUtils::make_path_string(&lo_loc.file.name);
|
||||
let values = make_values_str(&[
|
||||
("name", &c.name),
|
||||
("crate", &num),
|
||||
("file_name", &file_name)
|
||||
("file_name", &c.file_name)
|
||||
]);
|
||||
|
||||
self.record_raw(&format!("external_crate{}\n", values));
|
||||
@ -78,12 +64,7 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> {
|
||||
self.record_raw("end_external_crates\n");
|
||||
}
|
||||
|
||||
fn enum_data(&mut self, span: Span, data: EnumData) {
|
||||
if self.dump_spans {
|
||||
self.dump_span("enum", span);
|
||||
return;
|
||||
}
|
||||
|
||||
fn enum_data(&mut self, data: EnumData) {
|
||||
let id = data.id.to_string();
|
||||
let scope = data.scope.to_string();
|
||||
let values = make_values_str(&[
|
||||
@ -96,12 +77,7 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> {
|
||||
self.record("enum", data.span, values);
|
||||
}
|
||||
|
||||
fn extern_crate(&mut self, span: Span, data: ExternCrateData) {
|
||||
if self.dump_spans {
|
||||
self.dump_span("extern_crate", span);
|
||||
return;
|
||||
}
|
||||
|
||||
fn extern_crate(&mut self, data: ExternCrateData) {
|
||||
let id = data.id.to_string();
|
||||
let crate_num = data.crate_num.to_string();
|
||||
let scope = data.scope.to_string();
|
||||
@ -116,12 +92,7 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> {
|
||||
self.record("extern_crate", data.span, values);
|
||||
}
|
||||
|
||||
fn impl_data(&mut self, span: Span, data: ImplData) {
|
||||
if self.dump_spans {
|
||||
self.dump_span("impl", span);
|
||||
return;
|
||||
}
|
||||
|
||||
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());
|
||||
|
||||
@ -144,10 +115,6 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> {
|
||||
}
|
||||
|
||||
fn inheritance(&mut self, data: InheritanceData) {
|
||||
if self.dump_spans {
|
||||
return;
|
||||
}
|
||||
|
||||
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();
|
||||
@ -162,12 +129,7 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> {
|
||||
self.record("inheritance", data.span, values);
|
||||
}
|
||||
|
||||
fn function(&mut self, span: Span, data: FunctionData) {
|
||||
if self.dump_spans {
|
||||
self.dump_span("function", span);
|
||||
return;
|
||||
}
|
||||
|
||||
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())
|
||||
@ -186,12 +148,7 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> {
|
||||
self.record("function", data.span, values);
|
||||
}
|
||||
|
||||
fn function_ref(&mut self, span: Span, data: FunctionRefData) {
|
||||
if self.dump_spans {
|
||||
self.dump_span("fn_ref", span);
|
||||
return;
|
||||
}
|
||||
|
||||
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 scope = data.scope.to_string();
|
||||
@ -205,12 +162,7 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> {
|
||||
self.record("fn_ref", data.span, values);
|
||||
}
|
||||
|
||||
fn function_call(&mut self, span: Span, data: FunctionCallData) {
|
||||
if self.dump_spans {
|
||||
self.dump_span("fn_call", span);
|
||||
return;
|
||||
}
|
||||
|
||||
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 qualname = String::new();
|
||||
@ -225,12 +177,7 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> {
|
||||
self.record("fn_call", data.span, values);
|
||||
}
|
||||
|
||||
fn method(&mut self, span: Span, data: MethodData) {
|
||||
if self.dump_spans {
|
||||
self.dump_span("method_decl", span);
|
||||
return;
|
||||
}
|
||||
|
||||
fn method(&mut self, data: MethodData) {
|
||||
let id = data.id.to_string();
|
||||
let scope = data.scope.to_string();
|
||||
let values = make_values_str(&[
|
||||
@ -239,15 +186,10 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> {
|
||||
("scopeid", &scope)
|
||||
]);
|
||||
|
||||
self.record("method_decl", span, values);
|
||||
self.record("method_decl", data.span, values);
|
||||
}
|
||||
|
||||
fn method_call(&mut self, span: Span, data: MethodCallData) {
|
||||
if self.dump_spans {
|
||||
self.dump_span("method_call", span);
|
||||
return;
|
||||
}
|
||||
|
||||
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()),
|
||||
@ -269,12 +211,7 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> {
|
||||
self.record("method_call", data.span, values);
|
||||
}
|
||||
|
||||
fn macro_data(&mut self, span: Span, data: MacroData) {
|
||||
if self.dump_spans {
|
||||
self.dump_span("macro", span);
|
||||
return;
|
||||
}
|
||||
|
||||
fn macro_data(&mut self, data: MacroData) {
|
||||
let values = make_values_str(&[
|
||||
("name", &data.name),
|
||||
("qualname", &data.qualname)
|
||||
@ -283,12 +220,7 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> {
|
||||
self.record("macro", data.span, values);
|
||||
}
|
||||
|
||||
fn macro_use(&mut self, span: Span, data: MacroUseData) {
|
||||
if self.dump_spans {
|
||||
self.dump_span("macro_use", span);
|
||||
return;
|
||||
}
|
||||
|
||||
fn macro_use(&mut self, data: MacroUseData) {
|
||||
let scope = data.scope.to_string();
|
||||
let values = make_values_str(&[
|
||||
("callee_name", &data.name),
|
||||
@ -300,10 +232,6 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> {
|
||||
}
|
||||
|
||||
fn mod_data(&mut self, data: ModData) {
|
||||
if self.dump_spans {
|
||||
return;
|
||||
}
|
||||
|
||||
let id = data.id.to_string();
|
||||
let scope = data.scope.to_string();
|
||||
let values = make_values_str(&[
|
||||
@ -316,12 +244,7 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> {
|
||||
self.record("module", data.span, values);
|
||||
}
|
||||
|
||||
fn mod_ref(&mut self, span: Span, data: ModRefData) {
|
||||
if self.dump_spans {
|
||||
self.dump_span("mod_ref", span);
|
||||
return;
|
||||
}
|
||||
|
||||
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())
|
||||
@ -338,12 +261,7 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> {
|
||||
self.record("mod_ref", data.span, values);
|
||||
}
|
||||
|
||||
fn struct_data(&mut self, span: Span, data: StructData) {
|
||||
if self.dump_spans {
|
||||
self.dump_span("struct", span);
|
||||
return;
|
||||
}
|
||||
|
||||
fn struct_data(&mut self, data: StructData) {
|
||||
let id = data.id.to_string();
|
||||
let ctor_id = data.ctor_id.to_string();
|
||||
let scope = data.scope.to_string();
|
||||
@ -358,12 +276,7 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> {
|
||||
self.record("struct", data.span, values);
|
||||
}
|
||||
|
||||
fn struct_variant(&mut self, span: Span, data: StructVariantData) {
|
||||
if self.dump_spans {
|
||||
self.dump_span("variant_struct", span);
|
||||
return;
|
||||
}
|
||||
|
||||
fn struct_variant(&mut self, data: StructVariantData) {
|
||||
let id = data.id.to_string();
|
||||
let scope = data.scope.to_string();
|
||||
let values = make_values_str(&[
|
||||
@ -378,12 +291,7 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> {
|
||||
self.record("variant_struct", data.span, values);
|
||||
}
|
||||
|
||||
fn trait_data(&mut self, span: Span, data: TraitData) {
|
||||
if self.dump_spans {
|
||||
self.dump_span("trait", span);
|
||||
return;
|
||||
}
|
||||
|
||||
fn trait_data(&mut self, data: TraitData) {
|
||||
let id = data.id.to_string();
|
||||
let scope = data.scope.to_string();
|
||||
let values = make_values_str(&[
|
||||
@ -396,12 +304,7 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> {
|
||||
self.record("trait", data.span, values);
|
||||
}
|
||||
|
||||
fn tuple_variant(&mut self, span: Span, data: TupleVariantData) {
|
||||
if self.dump_spans {
|
||||
self.dump_span("variant", span);
|
||||
return;
|
||||
}
|
||||
|
||||
fn tuple_variant(&mut self, data: TupleVariantData) {
|
||||
let id = data.id.to_string();
|
||||
let scope = data.scope.to_string();
|
||||
let values = make_values_str(&[
|
||||
@ -416,12 +319,7 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> {
|
||||
self.record("variant", data.span, values);
|
||||
}
|
||||
|
||||
fn type_ref(&mut self, span: Span, data: TypeRefData) {
|
||||
if self.dump_spans {
|
||||
self.dump_span("type_ref", span);
|
||||
return;
|
||||
}
|
||||
|
||||
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())
|
||||
@ -438,12 +336,7 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> {
|
||||
self.record("type_ref", data.span, values);
|
||||
}
|
||||
|
||||
fn typedef(&mut self, span: Span, data: TypedefData) {
|
||||
if self.dump_spans {
|
||||
self.dump_span("typedef", span);
|
||||
return;
|
||||
}
|
||||
|
||||
fn typedef(&mut self, data: TypedefData) {
|
||||
let id = data.id.to_string();
|
||||
let values = make_values_str(&[
|
||||
("id", &id),
|
||||
@ -454,12 +347,7 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> {
|
||||
self.record("typedef", data.span, values);
|
||||
}
|
||||
|
||||
fn use_data(&mut self, span: Span, data: UseData) {
|
||||
if self.dump_spans {
|
||||
self.dump_span("use_alias", span);
|
||||
return;
|
||||
}
|
||||
|
||||
fn use_data(&mut self, data: UseData) {
|
||||
let mod_id = data.mod_id.unwrap_or(null_def_id());
|
||||
|
||||
let id = data.id.to_string();
|
||||
@ -477,12 +365,7 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> {
|
||||
self.record("use_alias", data.span, values);
|
||||
}
|
||||
|
||||
fn use_glob(&mut self, span: Span, data: UseGlobData) {
|
||||
if self.dump_spans {
|
||||
self.dump_span("use_glob", span);
|
||||
return;
|
||||
}
|
||||
|
||||
fn use_glob(&mut self, data: UseGlobData) {
|
||||
let names = data.names.join(", ");
|
||||
|
||||
let id = data.id.to_string();
|
||||
@ -496,12 +379,7 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> {
|
||||
self.record("use_glob", data.span, values);
|
||||
}
|
||||
|
||||
fn variable(&mut self, span: Span, data: VariableData) {
|
||||
if self.dump_spans {
|
||||
self.dump_span("variable", span);
|
||||
return;
|
||||
}
|
||||
|
||||
fn variable(&mut self, data: VariableData) {
|
||||
let id = data.id.to_string();
|
||||
let scope = data.scope.to_string();
|
||||
let values = make_values_str(&[
|
||||
@ -516,12 +394,7 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> {
|
||||
self.record("variable", data.span, values);
|
||||
}
|
||||
|
||||
fn variable_ref(&mut self, span: Span, data: VariableRefData) {
|
||||
if self.dump_spans {
|
||||
self.dump_span("var_ref", span);
|
||||
return;
|
||||
}
|
||||
|
||||
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 scope = data.scope.to_string();
|
||||
|
@ -18,16 +18,47 @@ use std::hash::Hasher;
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::ty;
|
||||
use syntax::ast::{CrateNum, NodeId};
|
||||
use syntax::codemap::Span;
|
||||
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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CrateData {
|
||||
pub name: String,
|
||||
pub number: u32,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
/// Data for any entity in the Rust language. The actual data contained varies
|
||||
/// with the kind of entity being queried. See the nested structs for details.
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, RustcEncodable)]
|
||||
pub enum Data {
|
||||
/// Data for Enums.
|
||||
EnumData(EnumData),
|
||||
@ -79,22 +110,24 @@ pub enum Data {
|
||||
}
|
||||
|
||||
/// Data for the prelude of a crate.
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, RustcEncodable)]
|
||||
pub struct CratePreludeData {
|
||||
pub crate_name: String,
|
||||
pub crate_root: Option<String>,
|
||||
pub external_crates: Vec<ExternalCrateData>
|
||||
pub crate_root: String,
|
||||
pub external_crates: Vec<ExternalCrateData>,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
/// Data for external crates in the prelude of a crate.
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, RustcEncodable)]
|
||||
pub struct ExternalCrateData {
|
||||
pub name: String,
|
||||
pub num: CrateNum
|
||||
pub num: CrateNum,
|
||||
pub file_name: String,
|
||||
}
|
||||
|
||||
/// Data for enum declarations.
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, RustcEncodable)]
|
||||
pub struct EnumData {
|
||||
pub id: NodeId,
|
||||
pub value: String,
|
||||
@ -104,7 +137,7 @@ pub struct EnumData {
|
||||
}
|
||||
|
||||
/// Data for extern crates.
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, RustcEncodable)]
|
||||
pub struct ExternCrateData {
|
||||
pub id: NodeId,
|
||||
pub name: String,
|
||||
@ -115,7 +148,7 @@ pub struct ExternCrateData {
|
||||
}
|
||||
|
||||
/// Data about a function call.
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, RustcEncodable)]
|
||||
pub struct FunctionCallData {
|
||||
pub span: Span,
|
||||
pub scope: NodeId,
|
||||
@ -123,7 +156,7 @@ pub struct FunctionCallData {
|
||||
}
|
||||
|
||||
/// Data for all kinds of functions and methods.
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, RustcEncodable)]
|
||||
pub struct FunctionData {
|
||||
pub id: NodeId,
|
||||
pub name: String,
|
||||
@ -134,14 +167,14 @@ pub struct FunctionData {
|
||||
}
|
||||
|
||||
/// Data about a function call.
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, RustcEncodable)]
|
||||
pub struct FunctionRefData {
|
||||
pub span: Span,
|
||||
pub scope: NodeId,
|
||||
pub ref_id: DefId,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, RustcEncodable)]
|
||||
pub struct ImplData {
|
||||
pub id: NodeId,
|
||||
pub span: Span,
|
||||
@ -150,7 +183,7 @@ pub struct ImplData {
|
||||
pub self_ref: Option<DefId>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, RustcEncodable)]
|
||||
// FIXME: this struct should not exist. However, removing it requires heavy
|
||||
// refactoring of dump_visitor.rs. See PR 31838 for more info.
|
||||
pub struct ImplData2 {
|
||||
@ -164,7 +197,7 @@ pub struct ImplData2 {
|
||||
pub self_ref: Option<TypeRefData>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, RustcEncodable)]
|
||||
pub struct InheritanceData {
|
||||
pub span: Span,
|
||||
pub base_id: DefId,
|
||||
@ -172,7 +205,7 @@ pub struct InheritanceData {
|
||||
}
|
||||
|
||||
/// Data about a macro declaration.
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, RustcEncodable)]
|
||||
pub struct MacroData {
|
||||
pub span: Span,
|
||||
pub name: String,
|
||||
@ -180,7 +213,7 @@ pub struct MacroData {
|
||||
}
|
||||
|
||||
/// Data about a macro use.
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, RustcEncodable)]
|
||||
pub struct MacroUseData {
|
||||
pub span: Span,
|
||||
pub name: String,
|
||||
@ -193,7 +226,7 @@ pub struct MacroUseData {
|
||||
}
|
||||
|
||||
/// Data about a method call.
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, RustcEncodable)]
|
||||
pub struct MethodCallData {
|
||||
pub span: Span,
|
||||
pub scope: NodeId,
|
||||
@ -202,7 +235,7 @@ pub struct MethodCallData {
|
||||
}
|
||||
|
||||
/// Data for method declarations (methods with a body are treated as functions).
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, RustcEncodable)]
|
||||
pub struct MethodData {
|
||||
pub id: NodeId,
|
||||
pub qualname: String,
|
||||
@ -211,7 +244,7 @@ pub struct MethodData {
|
||||
}
|
||||
|
||||
/// Data for modules.
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, RustcEncodable)]
|
||||
pub struct ModData {
|
||||
pub id: NodeId,
|
||||
pub name: String,
|
||||
@ -222,7 +255,7 @@ pub struct ModData {
|
||||
}
|
||||
|
||||
/// Data for a reference to a module.
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, RustcEncodable)]
|
||||
pub struct ModRefData {
|
||||
pub span: Span,
|
||||
pub scope: NodeId,
|
||||
@ -230,7 +263,7 @@ pub struct ModRefData {
|
||||
pub qualname: String
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, RustcEncodable)]
|
||||
pub struct StructData {
|
||||
pub span: Span,
|
||||
pub id: NodeId,
|
||||
@ -240,7 +273,7 @@ pub struct StructData {
|
||||
pub value: String
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, RustcEncodable)]
|
||||
pub struct StructVariantData {
|
||||
pub span: Span,
|
||||
pub id: NodeId,
|
||||
@ -250,7 +283,7 @@ pub struct StructVariantData {
|
||||
pub scope: NodeId
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, RustcEncodable)]
|
||||
pub struct TraitData {
|
||||
pub span: Span,
|
||||
pub id: NodeId,
|
||||
@ -259,7 +292,7 @@ pub struct TraitData {
|
||||
pub value: String
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, RustcEncodable)]
|
||||
pub struct TupleVariantData {
|
||||
pub span: Span,
|
||||
pub id: NodeId,
|
||||
@ -271,7 +304,7 @@ pub struct TupleVariantData {
|
||||
}
|
||||
|
||||
/// Data for a typedef.
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, RustcEncodable)]
|
||||
pub struct TypedefData {
|
||||
pub id: NodeId,
|
||||
pub span: Span,
|
||||
@ -280,7 +313,7 @@ pub struct TypedefData {
|
||||
}
|
||||
|
||||
/// Data for a reference to a type or trait.
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, RustcEncodable)]
|
||||
pub struct TypeRefData {
|
||||
pub span: Span,
|
||||
pub scope: NodeId,
|
||||
@ -288,7 +321,7 @@ pub struct TypeRefData {
|
||||
pub qualname: String,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, RustcEncodable)]
|
||||
pub struct UseData {
|
||||
pub id: NodeId,
|
||||
pub span: Span,
|
||||
@ -297,7 +330,7 @@ pub struct UseData {
|
||||
pub scope: NodeId
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, RustcEncodable)]
|
||||
pub struct UseGlobData {
|
||||
pub id: NodeId,
|
||||
pub span: Span,
|
||||
@ -306,7 +339,7 @@ pub struct UseGlobData {
|
||||
}
|
||||
|
||||
/// Data for local and global variables (consts and statics).
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, RustcEncodable)]
|
||||
pub struct VariableData {
|
||||
pub id: NodeId,
|
||||
pub name: String,
|
||||
@ -319,7 +352,7 @@ pub struct VariableData {
|
||||
|
||||
/// 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)]
|
||||
#[derive(Debug, RustcEncodable)]
|
||||
pub struct VariableRefData {
|
||||
pub name: String,
|
||||
pub span: Span,
|
||||
|
@ -8,33 +8,31 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use syntax::codemap::Span;
|
||||
|
||||
use super::data::*;
|
||||
|
||||
pub trait Dump {
|
||||
fn crate_prelude(&mut self, _: Span, _: CratePreludeData) {}
|
||||
fn enum_data(&mut self, _: Span, _: EnumData) {}
|
||||
fn extern_crate(&mut self, _: Span, _: ExternCrateData) {}
|
||||
fn impl_data(&mut self, _: Span, _: ImplData) {}
|
||||
fn inheritance(&mut self, _: InheritanceData) {}
|
||||
fn function(&mut self, _: Span, _: FunctionData) {}
|
||||
fn function_ref(&mut self, _: Span, _: FunctionRefData) {}
|
||||
fn function_call(&mut self, _: Span, _: FunctionCallData) {}
|
||||
fn method(&mut self, _: Span, _: MethodData) {}
|
||||
fn method_call(&mut self, _: Span, _: MethodCallData) {}
|
||||
fn macro_data(&mut self, _: Span, _: MacroData) {}
|
||||
fn macro_use(&mut self, _: Span, _: MacroUseData) {}
|
||||
fn mod_data(&mut self, _: ModData) {}
|
||||
fn mod_ref(&mut self, _: Span, _: ModRefData) {}
|
||||
fn struct_data(&mut self, _: Span, _: StructData) {}
|
||||
fn struct_variant(&mut self, _: Span, _: StructVariantData) {}
|
||||
fn trait_data(&mut self, _: Span, _: TraitData) {}
|
||||
fn tuple_variant(&mut self, _: Span, _: TupleVariantData) {}
|
||||
fn type_ref(&mut self, _: Span, _: TypeRefData) {}
|
||||
fn typedef(&mut self, _: Span, _: TypedefData) {}
|
||||
fn use_data(&mut self, _: Span, _: UseData) {}
|
||||
fn use_glob(&mut self, _: Span, _: UseGlobData) {}
|
||||
fn variable(&mut self, _: Span, _: VariableData) {}
|
||||
fn variable_ref(&mut self, _: Span, _: VariableRefData) {}
|
||||
fn crate_prelude(&mut self, CratePreludeData) {}
|
||||
fn enum_data(&mut self, EnumData) {}
|
||||
fn extern_crate(&mut self, ExternCrateData) {}
|
||||
fn impl_data(&mut self, ImplData) {}
|
||||
fn inheritance(&mut self, InheritanceData) {}
|
||||
fn function(&mut self, FunctionData) {}
|
||||
fn function_ref(&mut self, FunctionRefData) {}
|
||||
fn function_call(&mut self, FunctionCallData) {}
|
||||
fn method(&mut self, MethodData) {}
|
||||
fn method_call(&mut self, MethodCallData) {}
|
||||
fn macro_data(&mut self, MacroData) {}
|
||||
fn macro_use(&mut self, MacroUseData) {}
|
||||
fn mod_data(&mut self, ModData) {}
|
||||
fn mod_ref(&mut self, ModRefData) {}
|
||||
fn struct_data(&mut self, StructData) {}
|
||||
fn struct_variant(&mut self, StructVariantData) {}
|
||||
fn trait_data(&mut self, TraitData) {}
|
||||
fn tuple_variant(&mut self, TupleVariantData) {}
|
||||
fn type_ref(&mut self, TypeRefData) {}
|
||||
fn typedef(&mut self, TypedefData) {}
|
||||
fn use_data(&mut self, UseData) {}
|
||||
fn use_glob(&mut self, UseGlobData) {}
|
||||
fn variable(&mut self, VariableData) {}
|
||||
fn variable_ref(&mut self, VariableRefData) {}
|
||||
}
|
||||
|
@ -119,20 +119,23 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
|
||||
|
||||
// Info about all the external crates referenced from this crate.
|
||||
let external_crates = self.save_ctxt.get_external_crates().into_iter().map(|c| {
|
||||
let lo_loc = self.span.sess.codemap().lookup_char_pos(c.span.lo);
|
||||
ExternalCrateData {
|
||||
name: c.name,
|
||||
num: c.number
|
||||
num: c.number,
|
||||
file_name: SpanUtils::make_path_string(&lo_loc.file.name),
|
||||
}
|
||||
}).collect();
|
||||
|
||||
// The current crate.
|
||||
let data = CratePreludeData {
|
||||
crate_name: name.into(),
|
||||
crate_root: crate_root,
|
||||
external_crates: external_crates
|
||||
crate_root: crate_root.unwrap_or("<no source>".to_owned()),
|
||||
external_crates: external_crates,
|
||||
span: krate.span,
|
||||
};
|
||||
|
||||
self.dumper.crate_prelude(krate.span, data);
|
||||
self.dumper.crate_prelude(data);
|
||||
}
|
||||
|
||||
// Return all non-empty prefixes of a path.
|
||||
@ -197,7 +200,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
|
||||
} else {
|
||||
qualname.clone()
|
||||
};
|
||||
self.dumper.mod_ref(path.span, ModRefData {
|
||||
self.dumper.mod_ref(ModRefData {
|
||||
span: *span,
|
||||
qualname: qualname,
|
||||
scope: self.cur_scope,
|
||||
@ -222,7 +225,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
|
||||
} else {
|
||||
qualname.clone()
|
||||
};
|
||||
self.dumper.mod_ref(path.span, ModRefData {
|
||||
self.dumper.mod_ref(ModRefData {
|
||||
span: *span,
|
||||
qualname: qualname,
|
||||
scope: self.cur_scope,
|
||||
@ -243,7 +246,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
|
||||
|
||||
// write the trait part of the sub-path
|
||||
let (ref span, ref qualname) = sub_paths[len-2];
|
||||
self.dumper.type_ref(path.span, TypeRefData {
|
||||
self.dumper.type_ref(TypeRefData {
|
||||
ref_id: None,
|
||||
span: *span,
|
||||
qualname: qualname.to_owned(),
|
||||
@ -256,7 +259,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
|
||||
}
|
||||
let sub_paths = &sub_paths[..len-2];
|
||||
for &(ref span, ref qualname) in sub_paths {
|
||||
self.dumper.mod_ref(path.span, ModRefData {
|
||||
self.dumper.mod_ref(ModRefData {
|
||||
span: *span,
|
||||
qualname: qualname.to_owned(),
|
||||
scope: self.cur_scope,
|
||||
@ -298,7 +301,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
|
||||
match def {
|
||||
Def::Mod(_) |
|
||||
Def::ForeignMod(_) => {
|
||||
self.dumper.mod_ref(span, ModRefData {
|
||||
self.dumper.mod_ref(ModRefData {
|
||||
span: sub_span.expect("No span found for mod ref"),
|
||||
ref_id: Some(def_id),
|
||||
scope: scope,
|
||||
@ -310,7 +313,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
|
||||
Def::TyAlias(..) |
|
||||
Def::AssociatedTy(..) |
|
||||
Def::Trait(_) => {
|
||||
self.dumper.type_ref(span, TypeRefData {
|
||||
self.dumper.type_ref(TypeRefData {
|
||||
span: sub_span.expect("No span found for type ref"),
|
||||
ref_id: Some(def_id),
|
||||
scope: scope,
|
||||
@ -323,7 +326,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
|
||||
Def::Local(..) |
|
||||
Def::Variant(..) |
|
||||
Def::Upvar(..) => {
|
||||
self.dumper.variable_ref(span, VariableRefData {
|
||||
self.dumper.variable_ref(VariableRefData {
|
||||
span: sub_span.expect("No span found for var ref"),
|
||||
ref_id: def_id,
|
||||
scope: scope,
|
||||
@ -331,7 +334,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
|
||||
}.normalize(&self.tcx));
|
||||
}
|
||||
Def::Fn(..) => {
|
||||
self.dumper.function_ref(span, FunctionRefData {
|
||||
self.dumper.function_ref(FunctionRefData {
|
||||
span: sub_span.expect("No span found for fn ref"),
|
||||
ref_id: def_id,
|
||||
scope: scope
|
||||
@ -362,7 +365,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
|
||||
// variable name, but who knows?)
|
||||
let sub_span = span_utils.span_for_last_ident(p.span);
|
||||
if !self.span.filter_generated(sub_span, p.span) {
|
||||
self.dumper.variable(p.span, VariableData {
|
||||
self.dumper.variable(VariableData {
|
||||
id: id,
|
||||
span: sub_span.expect("No span found for variable"),
|
||||
name: path_to_string(p),
|
||||
@ -388,12 +391,12 @@ 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(span, method_data.clone().normalize(&self.tcx));
|
||||
self.dumper.function(method_data.clone().normalize(&self.tcx));
|
||||
}
|
||||
self.process_formals(&sig.decl.inputs, &method_data.qualname);
|
||||
} else {
|
||||
if !self.span.filter_generated(Some(method_data.span), span) {
|
||||
self.dumper.method(span, MethodData {
|
||||
self.dumper.method(MethodData {
|
||||
id: method_data.id,
|
||||
span: method_data.span,
|
||||
scope: method_data.scope,
|
||||
@ -423,7 +426,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.path.span, trait_ref_data.normalize(&self.tcx));
|
||||
self.dumper.type_ref(trait_ref_data.normalize(&self.tcx));
|
||||
}
|
||||
|
||||
visit::walk_path(self, &trait_ref.path);
|
||||
@ -436,7 +439,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
|
||||
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.span, field_data.normalize(&self.tcx));
|
||||
self.dumper.variable(field_data.normalize(&self.tcx));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -460,7 +463,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
|
||||
escape(self.span.snippet(param_ss)),
|
||||
id);
|
||||
if !self.span.filter_generated(Some(param_ss), full_span) {
|
||||
self.dumper.typedef(full_span, TypedefData {
|
||||
self.dumper.typedef(TypedefData {
|
||||
span: param_ss,
|
||||
id: param.id,
|
||||
qualname: name,
|
||||
@ -479,7 +482,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(item.span, fn_data.clone().normalize(&self.tcx));
|
||||
self.dumper.function(fn_data.clone().normalize(&self.tcx));
|
||||
}
|
||||
|
||||
self.process_formals(&decl.inputs, &fn_data.qualname);
|
||||
@ -503,7 +506,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
|
||||
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(item.span, var_data.normalize(&self.tcx));
|
||||
self.dumper.variable(var_data.normalize(&self.tcx));
|
||||
}
|
||||
}
|
||||
self.visit_ty(&typ);
|
||||
@ -521,7 +524,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
|
||||
let sub_span = self.span.sub_span_after_keyword(span, keywords::Const);
|
||||
|
||||
if !self.span.filter_generated(sub_span, span) {
|
||||
self.dumper.variable(span, VariableData {
|
||||
self.dumper.variable(VariableData {
|
||||
span: sub_span.expect("No span found for variable"),
|
||||
id: id,
|
||||
name: name.to_string(),
|
||||
@ -546,7 +549,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
|
||||
let val = self.span.snippet(item.span);
|
||||
let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Struct);
|
||||
if !self.span.filter_generated(sub_span, item.span) {
|
||||
self.dumper.struct_data(item.span, StructData {
|
||||
self.dumper.struct_data(StructData {
|
||||
span: sub_span.expect("No span found for struct"),
|
||||
id: item.id,
|
||||
ctor_id: def.id(),
|
||||
@ -578,7 +581,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
|
||||
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(item.span, normalized);
|
||||
self.dumper.enum_data(normalized);
|
||||
}
|
||||
|
||||
for variant in &enum_definition.variants {
|
||||
@ -592,7 +595,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
|
||||
ast::VariantData::Struct(..) => {
|
||||
let sub_span = self.span.span_for_first_ident(variant.span);
|
||||
if !self.span.filter_generated(sub_span, variant.span) {
|
||||
self.dumper.struct_variant(variant.span, StructVariantData {
|
||||
self.dumper.struct_variant(StructVariantData {
|
||||
span: sub_span.expect("No span found for struct variant"),
|
||||
id: variant.node.data.id(),
|
||||
qualname: qualname,
|
||||
@ -605,7 +608,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
|
||||
_ => {
|
||||
let sub_span = self.span.span_for_first_ident(variant.span);
|
||||
if !self.span.filter_generated(sub_span, variant.span) {
|
||||
self.dumper.tuple_variant(variant.span, TupleVariantData {
|
||||
self.dumper.tuple_variant(TupleVariantData {
|
||||
span: sub_span.expect("No span found for tuple variant"),
|
||||
id: variant.node.data.id(),
|
||||
name: name.to_string(),
|
||||
@ -639,19 +642,19 @@ 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(item.span, self_ref.clone().normalize(&self.tcx));
|
||||
self.dumper.type_ref(self_ref.clone().normalize(&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(item.span, trait_ref_data.clone().normalize(&self.tcx));
|
||||
self.dumper.type_ref(trait_ref_data.clone().normalize(&self.tcx));
|
||||
}
|
||||
|
||||
visit::walk_path(self, &trait_ref.as_ref().unwrap().path);
|
||||
}
|
||||
|
||||
if !self.span.filter_generated(Some(impl_data.span), item.span) {
|
||||
self.dumper.impl_data(item.span, ImplData {
|
||||
self.dumper.impl_data(ImplData {
|
||||
id: impl_data.id,
|
||||
span: impl_data.span,
|
||||
scope: impl_data.scope,
|
||||
@ -678,7 +681,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
|
||||
let val = self.span.snippet(item.span);
|
||||
let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Trait);
|
||||
if !self.span.filter_generated(sub_span, item.span) {
|
||||
self.dumper.trait_data(item.span, TraitData {
|
||||
self.dumper.trait_data(TraitData {
|
||||
span: sub_span.expect("No span found for trait"),
|
||||
id: item.id,
|
||||
qualname: qualname.clone(),
|
||||
@ -702,7 +705,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
|
||||
if let Some(id) = self.lookup_type_ref(trait_ref.ref_id) {
|
||||
let sub_span = self.span.sub_span_for_type_name(trait_ref.path.span);
|
||||
if !self.span.filter_generated(sub_span, trait_ref.path.span) {
|
||||
self.dumper.type_ref(trait_ref.path.span, TypeRefData {
|
||||
self.dumper.type_ref(TypeRefData {
|
||||
span: sub_span.expect("No span found for trait ref"),
|
||||
ref_id: Some(id),
|
||||
scope: self.cur_scope,
|
||||
@ -759,7 +762,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
|
||||
if !self.span.filter_generated(Some(vrd.span), path.span) {
|
||||
match ref_kind {
|
||||
Some(recorder::TypeRef) => {
|
||||
self.dumper.type_ref(path.span, TypeRefData {
|
||||
self.dumper.type_ref(TypeRefData {
|
||||
span: vrd.span,
|
||||
ref_id: Some(vrd.ref_id),
|
||||
scope: vrd.scope,
|
||||
@ -767,14 +770,14 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
|
||||
}.normalize(&self.tcx));
|
||||
}
|
||||
Some(recorder::FnRef) => {
|
||||
self.dumper.function_ref(path.span, FunctionRefData {
|
||||
self.dumper.function_ref(FunctionRefData {
|
||||
span: vrd.span,
|
||||
ref_id: vrd.ref_id,
|
||||
scope: vrd.scope
|
||||
}.normalize(&self.tcx));
|
||||
}
|
||||
Some(recorder::ModRef) => {
|
||||
self.dumper.mod_ref(path.span, ModRefData {
|
||||
self.dumper.mod_ref( ModRefData {
|
||||
span: vrd.span,
|
||||
ref_id: Some(vrd.ref_id),
|
||||
scope: vrd.scope,
|
||||
@ -782,24 +785,24 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
|
||||
}.normalize(&self.tcx));
|
||||
}
|
||||
Some(recorder::VarRef) | None
|
||||
=> self.dumper.variable_ref(path.span, vrd.normalize(&self.tcx))
|
||||
=> self.dumper.variable_ref(vrd.normalize(&self.tcx))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Data::TypeRefData(trd) => {
|
||||
if !self.span.filter_generated(Some(trd.span), path.span) {
|
||||
self.dumper.type_ref(path.span, trd.normalize(&self.tcx));
|
||||
self.dumper.type_ref(trd.normalize(&self.tcx));
|
||||
}
|
||||
}
|
||||
Data::MethodCallData(mcd) => {
|
||||
if !self.span.filter_generated(Some(mcd.span), path.span) {
|
||||
self.dumper.method_call(path.span, mcd.normalize(&self.tcx));
|
||||
self.dumper.method_call(mcd.normalize(&self.tcx));
|
||||
}
|
||||
}
|
||||
Data::FunctionCallData(fcd) => {
|
||||
if !self.span.filter_generated(Some(fcd.span), path.span) {
|
||||
self.dumper.function_call(path.span, fcd.normalize(&self.tcx));
|
||||
self.dumper.function_call(fcd.normalize(&self.tcx));
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
@ -841,7 +844,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(ex.span, struct_lit_data.normalize(&self.tcx));
|
||||
self.dumper.type_ref(struct_lit_data.normalize(&self.tcx));
|
||||
}
|
||||
|
||||
let scope = self.save_ctxt.enclosing_scope(ex.id);
|
||||
@ -851,7 +854,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.ident.span, field_data.normalize(&self.tcx));
|
||||
self.dumper.variable_ref(field_data.normalize(&self.tcx));
|
||||
}
|
||||
}
|
||||
|
||||
@ -866,7 +869,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(ex.span, mcd.normalize(&self.tcx));
|
||||
self.dumper.method_call(mcd.normalize(&self.tcx));
|
||||
}
|
||||
}
|
||||
|
||||
@ -886,7 +889,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
|
||||
let sub_span = self.span.span_for_first_ident(span);
|
||||
if let Some(f) = variant.find_field_named(field.ident.name) {
|
||||
if !self.span.filter_generated(sub_span, span) {
|
||||
self.dumper.variable_ref(span, VariableRefData {
|
||||
self.dumper.variable_ref(VariableRefData {
|
||||
span: sub_span.expect("No span fund for var ref"),
|
||||
ref_id: f.did,
|
||||
scope: self.cur_scope,
|
||||
@ -922,7 +925,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
|
||||
let sub_span = self.span.span_for_last_ident(p.span);
|
||||
// Rust uses the id of the pattern for var lookups, so we'll use it too.
|
||||
if !self.span.filter_generated(sub_span, p.span) {
|
||||
self.dumper.variable(p.span, VariableData {
|
||||
self.dumper.variable(VariableData {
|
||||
span: sub_span.expect("No span found for variable"),
|
||||
id: id,
|
||||
name: path_to_string(p),
|
||||
@ -956,7 +959,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
|
||||
&& !data.imported {
|
||||
self.mac_defs.insert(data.callee_span);
|
||||
if let Some(sub_span) = self.span.span_for_macro_def_name(data.callee_span) {
|
||||
self.dumper.macro_data(data.callee_span, MacroData {
|
||||
self.dumper.macro_data(MacroData {
|
||||
span: sub_span,
|
||||
name: data.name.clone(),
|
||||
qualname: qualname.clone()
|
||||
@ -966,7 +969,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
|
||||
if !self.mac_uses.contains(&data.span) {
|
||||
self.mac_uses.insert(data.span);
|
||||
if let Some(sub_span) = self.span.span_for_macro_use_name(data.span) {
|
||||
self.dumper.macro_use(data.span, MacroUseData {
|
||||
self.dumper.macro_use(MacroUseData {
|
||||
span: sub_span,
|
||||
name: data.name,
|
||||
qualname: qualname,
|
||||
@ -1007,7 +1010,7 @@ impl<'v, 'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'v> for DumpVisitor<'l, 'tcx,
|
||||
};
|
||||
|
||||
if !self.span.filter_generated(sub_span, path.span) {
|
||||
self.dumper.use_data(path.span, UseData {
|
||||
self.dumper.use_data(UseData {
|
||||
span: sub_span.expect("No span found for use"),
|
||||
id: item.id,
|
||||
mod_id: mod_id,
|
||||
@ -1031,7 +1034,7 @@ impl<'v, 'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'v> for DumpVisitor<'l, 'tcx,
|
||||
let sub_span = self.span
|
||||
.sub_span_of_token(path.span, token::BinOp(token::Star));
|
||||
if !self.span.filter_generated(sub_span, path.span) {
|
||||
self.dumper.use_glob(path.span, UseGlobData {
|
||||
self.dumper.use_glob(UseGlobData {
|
||||
span: sub_span.expect("No span found for use glob"),
|
||||
id: item.id,
|
||||
names: names,
|
||||
@ -1073,7 +1076,7 @@ impl<'v, 'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'v> for DumpVisitor<'l, 'tcx,
|
||||
};
|
||||
|
||||
if !self.span.filter_generated(alias_span, item.span) {
|
||||
self.dumper.extern_crate(item.span, ExternCrateData {
|
||||
self.dumper.extern_crate(ExternCrateData {
|
||||
id: item.id,
|
||||
name: item.ident.to_string(),
|
||||
crate_num: cnum,
|
||||
@ -1109,7 +1112,7 @@ impl<'v, 'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'v> for DumpVisitor<'l, 'tcx,
|
||||
let value = ty_to_string(&ty);
|
||||
let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Type);
|
||||
if !self.span.filter_generated(sub_span, item.span) {
|
||||
self.dumper.typedef(item.span, TypedefData {
|
||||
self.dumper.typedef(TypedefData {
|
||||
span: sub_span.expect("No span found for typedef"),
|
||||
id: item.id,
|
||||
qualname: qualname.clone(),
|
||||
@ -1189,7 +1192,7 @@ impl<'v, 'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'v> for DumpVisitor<'l, 'tcx,
|
||||
if let Some(id) = self.lookup_type_ref(t.id) {
|
||||
let sub_span = self.span.sub_span_for_type_name(t.span);
|
||||
if !self.span.filter_generated(sub_span, t.span) {
|
||||
self.dumper.type_ref(t.span, TypeRefData {
|
||||
self.dumper.type_ref(TypeRefData {
|
||||
span: sub_span.expect("No span found for type ref"),
|
||||
ref_id: Some(id),
|
||||
scope: self.cur_scope,
|
||||
@ -1231,7 +1234,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(ex.span, field_data.normalize(&self.tcx));
|
||||
self.dumper.variable_ref(field_data.normalize(&self.tcx));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1244,7 +1247,7 @@ impl<'v, 'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'v> for DumpVisitor<'l, 'tcx,
|
||||
ty::TyStruct(def, _) => {
|
||||
let sub_span = self.span.sub_span_after_token(ex.span, token::Dot);
|
||||
if !self.span.filter_generated(sub_span, ex.span) {
|
||||
self.dumper.variable_ref(ex.span, VariableRefData {
|
||||
self.dumper.variable_ref(VariableRefData {
|
||||
span: sub_span.expect("No span found for var ref"),
|
||||
ref_id: def.struct_variant().fields[idx.node].did,
|
||||
scope: self.cur_scope,
|
||||
@ -1334,7 +1337,7 @@ impl<'v, 'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'v> for DumpVisitor<'l, 'tcx,
|
||||
assert!(p.segments.len() == 1,
|
||||
"qualified path for local variable def in arm");
|
||||
if !self.span.filter_generated(Some(p.span), p.span) {
|
||||
self.dumper.variable(p.span, VariableData {
|
||||
self.dumper.variable(VariableData {
|
||||
span: p.span,
|
||||
id: id,
|
||||
name: path_to_string(p),
|
||||
|
651
src/librustc_save_analysis/json_dumper.rs
Normal file
651
src/librustc_save_analysis/json_dumper.rs
Normal file
@ -0,0 +1,651 @@
|
||||
// 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::io::Write;
|
||||
|
||||
use rustc_serialize::json::as_json;
|
||||
use syntax::codemap::CodeMap;
|
||||
|
||||
use syntax::ast::CrateNum;
|
||||
|
||||
use super::data::{self, SpanData};
|
||||
use super::dump::Dump;
|
||||
|
||||
pub struct JsonDumper<'a, '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> {
|
||||
if let Err(_) = write!(writer, "[") {
|
||||
error!("Error writing output");
|
||||
}
|
||||
JsonDumper { output: writer, codemap:codemap, first: true }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b, W: Write> Drop for JsonDumper<'a, 'b, W> {
|
||||
fn drop(&mut self) {
|
||||
if let Err(_) = write!(self.output, "]") {
|
||||
error!("Error writing output");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_fn {
|
||||
($fn_name: ident, $data_type: ident) => {
|
||||
fn $fn_name(&mut self, data: data::$data_type) {
|
||||
if self.first {
|
||||
self.first = false;
|
||||
} else {
|
||||
if let Err(_) = write!(self.output, ",") {
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b, W: Write + 'b> Dump for JsonDumper<'a, 'b, W> {
|
||||
impl_fn!(crate_prelude, CratePreludeData);
|
||||
impl_fn!(enum_data, EnumData);
|
||||
impl_fn!(extern_crate, ExternCrateData);
|
||||
impl_fn!(impl_data, ImplData);
|
||||
impl_fn!(inheritance, InheritanceData);
|
||||
impl_fn!(function, FunctionData);
|
||||
impl_fn!(function_ref, FunctionRefData);
|
||||
impl_fn!(function_call, FunctionCallData);
|
||||
impl_fn!(method, MethodData);
|
||||
impl_fn!(method_call, MethodCallData);
|
||||
impl_fn!(macro_data, MacroData);
|
||||
impl_fn!(macro_use, MacroUseData);
|
||||
impl_fn!(mod_data, ModData);
|
||||
impl_fn!(mod_ref, ModRefData);
|
||||
impl_fn!(struct_data, StructData);
|
||||
impl_fn!(struct_variant, StructVariantData);
|
||||
impl_fn!(trait_data, TraitData);
|
||||
impl_fn!(tuple_variant, TupleVariantData);
|
||||
impl_fn!(type_ref, TypeRefData);
|
||||
impl_fn!(typedef, TypedefData);
|
||||
impl_fn!(use_data, UseData);
|
||||
impl_fn!(use_glob, UseGlobData);
|
||||
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(),
|
||||
}
|
||||
}
|
||||
}
|
@ -26,6 +26,7 @@
|
||||
|
||||
#[macro_use] extern crate log;
|
||||
#[macro_use] extern crate syntax;
|
||||
extern crate serialize as rustc_serialize;
|
||||
|
||||
use rustc::hir::{self, lowering};
|
||||
use rustc::hir::map::NodeItem;
|
||||
@ -45,6 +46,7 @@ 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;
|
||||
@ -52,6 +54,7 @@ mod dump_visitor;
|
||||
pub mod span_utils;
|
||||
|
||||
pub use self::csv_dumper::CsvDumper;
|
||||
pub use self::json_dumper::JsonDumper;
|
||||
pub use self::data::*;
|
||||
pub use self::dump::Dump;
|
||||
pub use self::dump_visitor::DumpVisitor;
|
||||
@ -104,9 +107,17 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
||||
let mut result = Vec::new();
|
||||
|
||||
for n in self.tcx.sess.cstore.crates() {
|
||||
let span = match self.tcx.sess.cstore.extern_crate(n) {
|
||||
Some(ref c) => c.span,
|
||||
None => {
|
||||
debug!("Skipping crate {}, no data", n);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
result.push(CrateData {
|
||||
name: (&self.tcx.sess.cstore.crate_name(n)[..]).to_owned(),
|
||||
number: n,
|
||||
span: span,
|
||||
});
|
||||
}
|
||||
|
||||
@ -677,12 +688,28 @@ impl<'v> Visitor<'v> for PathCollector {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum Format {
|
||||
Csv,
|
||||
Json,
|
||||
}
|
||||
|
||||
impl Format {
|
||||
fn extension(&self) -> &'static str {
|
||||
match *self {
|
||||
Format::Csv => ".csv",
|
||||
Format::Json => ".json",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn process_crate<'l, 'tcx>(tcx: &'l TyCtxt<'tcx>,
|
||||
lcx: &'l lowering::LoweringContext<'l>,
|
||||
krate: &ast::Crate,
|
||||
analysis: &'l ty::CrateAnalysis<'l>,
|
||||
cratename: &str,
|
||||
odir: Option<&Path>) {
|
||||
odir: Option<&Path>,
|
||||
format: Format) {
|
||||
let _ignore = tcx.dep_graph.in_ignore();
|
||||
|
||||
assert!(analysis.glob_map.is_some());
|
||||
@ -690,11 +717,11 @@ pub fn process_crate<'l, 'tcx>(tcx: &'l TyCtxt<'tcx>,
|
||||
info!("Dumping crate {}", cratename);
|
||||
|
||||
// find a path to dump our data to
|
||||
let mut root_path = match env::var_os("DXR_RUST_TEMP_FOLDER") {
|
||||
let mut root_path = match env::var_os("RUST_SAVE_ANALYSIS_FOLDER") {
|
||||
Some(val) => PathBuf::from(val),
|
||||
None => match odir {
|
||||
Some(val) => val.join("dxr"),
|
||||
None => PathBuf::from("dxr-temp"),
|
||||
Some(val) => val.join("save-analysis"),
|
||||
None => PathBuf::from("save-analysis-temp"),
|
||||
},
|
||||
};
|
||||
|
||||
@ -718,22 +745,32 @@ pub fn process_crate<'l, 'tcx>(tcx: &'l TyCtxt<'tcx>,
|
||||
};
|
||||
out_name.push_str(&cratename);
|
||||
out_name.push_str(&tcx.sess.opts.cg.extra_filename);
|
||||
out_name.push_str(".csv");
|
||||
out_name.push_str(format.extension());
|
||||
root_path.push(&out_name);
|
||||
let mut output_file = File::create(&root_path).unwrap_or_else(|e| {
|
||||
let disp = root_path.display();
|
||||
tcx.sess.fatal(&format!("Could not open {}: {}", disp, e));
|
||||
});
|
||||
root_path.pop();
|
||||
let output = &mut output_file;
|
||||
|
||||
let utils: SpanUtils<'tcx> = SpanUtils::new(&tcx.sess);
|
||||
let save_ctxt = SaveContext::new(tcx, lcx);
|
||||
let mut dumper = CsvDumper::new(&mut output_file, utils);
|
||||
let mut visitor = DumpVisitor::new(tcx, save_ctxt, analysis, &mut dumper);
|
||||
// FIXME: we don't write anything!
|
||||
|
||||
visitor.dump_crate_info(cratename, krate);
|
||||
visit::walk_crate(&mut visitor, krate);
|
||||
macro_rules! dump {
|
||||
($new_dumper: expr) => {{
|
||||
let mut dumper = $new_dumper;
|
||||
let mut visitor = DumpVisitor::new(tcx, save_ctxt, analysis, &mut dumper);
|
||||
|
||||
visitor.dump_crate_info(cratename, krate);
|
||||
visit::walk_crate(&mut visitor, krate);
|
||||
}}
|
||||
}
|
||||
|
||||
match format {
|
||||
Format::Csv => dump!(CsvDumper::new(output, utils)),
|
||||
Format::Json => dump!(JsonDumper::new(output, utils.sess.codemap())),
|
||||
}
|
||||
}
|
||||
|
||||
// Utility functions for the module.
|
||||
|
@ -3,4 +3,5 @@ all: code
|
||||
krate2: krate2.rs
|
||||
$(RUSTC) $<
|
||||
code: foo.rs krate2
|
||||
$(RUSTC) foo.rs -Zsave-analysis-csv
|
||||
$(RUSTC) foo.rs -Zsave-analysis
|
||||
|
Loading…
x
Reference in New Issue
Block a user