save-analysis: implement JSON dumps

This commit is contained in:
Nick Cameron 2016-04-25 20:54:00 +12:00
parent 40963c47f8
commit e7b8c5e3ab
8 changed files with 144 additions and 69 deletions

View File

@ -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 \ log syntax serialize rustc_llvm rustc_platform_intrinsics \
rustc_const_math rustc_const_eval rustc_incremental rustc_const_math rustc_const_eval rustc_incremental
DEPS_rustc_incremental := rbml rustc serialize rustc_data_structures 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 \ DEPS_rustc_typeck := rustc syntax rustc_platform_intrinsics rustc_const_math \
rustc_const_eval rustc_const_eval

View File

@ -12,3 +12,4 @@ crate-type = ["dylib"]
log = { path = "../liblog" } log = { path = "../liblog" }
rustc = { path = "../librustc" } rustc = { path = "../librustc" }
syntax = { path = "../libsyntax" } syntax = { path = "../libsyntax" }
serialize = { path = "../librustc_serialize" }

View File

@ -42,24 +42,20 @@ impl<'a, 'b, W: Write> CsvDumper<'a, 'b, W> {
} }
impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> { impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> {
fn crate_prelude(&mut self, span: Span, data: CratePreludeData) { fn crate_prelude(&mut self, data: CratePreludeData) {
let crate_root = data.crate_root.unwrap_or("<no source>".to_owned());
let values = make_values_str(&[ let values = make_values_str(&[
("name", &data.crate_name), ("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 { for c in data.external_crates {
let num = c.num.to_string(); 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(&[ let values = make_values_str(&[
("name", &c.name), ("name", &c.name),
("crate", &num), ("crate", &num),
("file_name", &file_name) ("file_name", &c.file_name)
]); ]);
self.record_raw(&format!("external_crate{}\n", values)); self.record_raw(&format!("external_crate{}\n", values));

View File

@ -23,11 +23,12 @@ use syntax::codemap::Span;
pub struct CrateData { pub struct CrateData {
pub name: String, pub name: String,
pub number: u32, pub number: u32,
pub span: Span,
} }
/// Data for any entity in the Rust language. The actual data contained varies /// 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. /// with the kind of entity being queried. See the nested structs for details.
#[derive(Debug)] #[derive(Debug, RustcEncodable)]
pub enum Data { pub enum Data {
/// Data for Enums. /// Data for Enums.
EnumData(EnumData), EnumData(EnumData),
@ -79,22 +80,24 @@ pub enum Data {
} }
/// Data for the prelude of a crate. /// Data for the prelude of a crate.
#[derive(Debug)] #[derive(Debug, RustcEncodable)]
pub struct CratePreludeData { pub struct CratePreludeData {
pub crate_name: String, pub crate_name: String,
pub crate_root: Option<String>, pub crate_root: String,
pub external_crates: Vec<ExternalCrateData> pub external_crates: Vec<ExternalCrateData>,
pub span: Span,
} }
/// Data for external crates in the prelude of a crate. /// Data for external crates in the prelude of a crate.
#[derive(Debug)] #[derive(Debug, RustcEncodable)]
pub struct ExternalCrateData { pub struct ExternalCrateData {
pub name: String, pub name: String,
pub num: CrateNum pub num: CrateNum,
pub file_name: String,
} }
/// Data for enum declarations. /// Data for enum declarations.
#[derive(Clone, Debug)] #[derive(Clone, Debug, RustcEncodable)]
pub struct EnumData { pub struct EnumData {
pub id: NodeId, pub id: NodeId,
pub value: String, pub value: String,
@ -104,7 +107,7 @@ pub struct EnumData {
} }
/// Data for extern crates. /// Data for extern crates.
#[derive(Debug)] #[derive(Debug, RustcEncodable)]
pub struct ExternCrateData { pub struct ExternCrateData {
pub id: NodeId, pub id: NodeId,
pub name: String, pub name: String,
@ -115,7 +118,7 @@ pub struct ExternCrateData {
} }
/// Data about a function call. /// Data about a function call.
#[derive(Debug)] #[derive(Debug, RustcEncodable)]
pub struct FunctionCallData { pub struct FunctionCallData {
pub span: Span, pub span: Span,
pub scope: NodeId, pub scope: NodeId,
@ -123,7 +126,7 @@ pub struct FunctionCallData {
} }
/// Data for all kinds of functions and methods. /// Data for all kinds of functions and methods.
#[derive(Clone, Debug)] #[derive(Clone, Debug, RustcEncodable)]
pub struct FunctionData { pub struct FunctionData {
pub id: NodeId, pub id: NodeId,
pub name: String, pub name: String,
@ -134,14 +137,14 @@ pub struct FunctionData {
} }
/// Data about a function call. /// Data about a function call.
#[derive(Debug)] #[derive(Debug, RustcEncodable)]
pub struct FunctionRefData { pub struct FunctionRefData {
pub span: Span, pub span: Span,
pub scope: NodeId, pub scope: NodeId,
pub ref_id: DefId, pub ref_id: DefId,
} }
#[derive(Debug)] #[derive(Debug, RustcEncodable)]
pub struct ImplData { pub struct ImplData {
pub id: NodeId, pub id: NodeId,
pub span: Span, pub span: Span,
@ -150,7 +153,7 @@ pub struct ImplData {
pub self_ref: Option<DefId>, pub self_ref: Option<DefId>,
} }
#[derive(Debug)] #[derive(Debug, RustcEncodable)]
// FIXME: this struct should not exist. However, removing it requires heavy // FIXME: this struct should not exist. However, removing it requires heavy
// refactoring of dump_visitor.rs. See PR 31838 for more info. // refactoring of dump_visitor.rs. See PR 31838 for more info.
pub struct ImplData2 { pub struct ImplData2 {
@ -164,7 +167,7 @@ pub struct ImplData2 {
pub self_ref: Option<TypeRefData>, pub self_ref: Option<TypeRefData>,
} }
#[derive(Debug)] #[derive(Debug, RustcEncodable)]
pub struct InheritanceData { pub struct InheritanceData {
pub span: Span, pub span: Span,
pub base_id: DefId, pub base_id: DefId,
@ -172,7 +175,7 @@ pub struct InheritanceData {
} }
/// Data about a macro declaration. /// Data about a macro declaration.
#[derive(Debug)] #[derive(Debug, RustcEncodable)]
pub struct MacroData { pub struct MacroData {
pub span: Span, pub span: Span,
pub name: String, pub name: String,
@ -180,7 +183,7 @@ pub struct MacroData {
} }
/// Data about a macro use. /// Data about a macro use.
#[derive(Debug)] #[derive(Debug, RustcEncodable)]
pub struct MacroUseData { pub struct MacroUseData {
pub span: Span, pub span: Span,
pub name: String, pub name: String,
@ -193,7 +196,7 @@ pub struct MacroUseData {
} }
/// Data about a method call. /// Data about a method call.
#[derive(Debug)] #[derive(Debug, RustcEncodable)]
pub struct MethodCallData { pub struct MethodCallData {
pub span: Span, pub span: Span,
pub scope: NodeId, pub scope: NodeId,
@ -202,7 +205,7 @@ pub struct MethodCallData {
} }
/// Data for method declarations (methods with a body are treated as functions). /// Data for method declarations (methods with a body are treated as functions).
#[derive(Clone, Debug)] #[derive(Clone, Debug, RustcEncodable)]
pub struct MethodData { pub struct MethodData {
pub id: NodeId, pub id: NodeId,
pub qualname: String, pub qualname: String,
@ -211,7 +214,7 @@ pub struct MethodData {
} }
/// Data for modules. /// Data for modules.
#[derive(Debug)] #[derive(Debug, RustcEncodable)]
pub struct ModData { pub struct ModData {
pub id: NodeId, pub id: NodeId,
pub name: String, pub name: String,
@ -222,7 +225,7 @@ pub struct ModData {
} }
/// Data for a reference to a module. /// Data for a reference to a module.
#[derive(Debug)] #[derive(Debug, RustcEncodable)]
pub struct ModRefData { pub struct ModRefData {
pub span: Span, pub span: Span,
pub scope: NodeId, pub scope: NodeId,
@ -230,7 +233,7 @@ pub struct ModRefData {
pub qualname: String pub qualname: String
} }
#[derive(Debug)] #[derive(Debug, RustcEncodable)]
pub struct StructData { pub struct StructData {
pub span: Span, pub span: Span,
pub id: NodeId, pub id: NodeId,
@ -240,7 +243,7 @@ pub struct StructData {
pub value: String pub value: String
} }
#[derive(Debug)] #[derive(Debug, RustcEncodable)]
pub struct StructVariantData { pub struct StructVariantData {
pub span: Span, pub span: Span,
pub id: NodeId, pub id: NodeId,
@ -250,7 +253,7 @@ pub struct StructVariantData {
pub scope: NodeId pub scope: NodeId
} }
#[derive(Debug)] #[derive(Debug, RustcEncodable)]
pub struct TraitData { pub struct TraitData {
pub span: Span, pub span: Span,
pub id: NodeId, pub id: NodeId,
@ -259,7 +262,7 @@ pub struct TraitData {
pub value: String pub value: String
} }
#[derive(Debug)] #[derive(Debug, RustcEncodable)]
pub struct TupleVariantData { pub struct TupleVariantData {
pub span: Span, pub span: Span,
pub id: NodeId, pub id: NodeId,
@ -271,7 +274,7 @@ pub struct TupleVariantData {
} }
/// Data for a typedef. /// Data for a typedef.
#[derive(Debug)] #[derive(Debug, RustcEncodable)]
pub struct TypedefData { pub struct TypedefData {
pub id: NodeId, pub id: NodeId,
pub span: Span, pub span: Span,
@ -280,7 +283,7 @@ pub struct TypedefData {
} }
/// Data for a reference to a type or trait. /// Data for a reference to a type or trait.
#[derive(Clone, Debug)] #[derive(Clone, Debug, RustcEncodable)]
pub struct TypeRefData { pub struct TypeRefData {
pub span: Span, pub span: Span,
pub scope: NodeId, pub scope: NodeId,
@ -288,7 +291,7 @@ pub struct TypeRefData {
pub qualname: String, pub qualname: String,
} }
#[derive(Debug)] #[derive(Debug, RustcEncodable)]
pub struct UseData { pub struct UseData {
pub id: NodeId, pub id: NodeId,
pub span: Span, pub span: Span,
@ -297,7 +300,7 @@ pub struct UseData {
pub scope: NodeId pub scope: NodeId
} }
#[derive(Debug)] #[derive(Debug, RustcEncodable)]
pub struct UseGlobData { pub struct UseGlobData {
pub id: NodeId, pub id: NodeId,
pub span: Span, pub span: Span,
@ -306,7 +309,7 @@ pub struct UseGlobData {
} }
/// Data for local and global variables (consts and statics). /// Data for local and global variables (consts and statics).
#[derive(Debug)] #[derive(Debug, RustcEncodable)]
pub struct VariableData { pub struct VariableData {
pub id: NodeId, pub id: NodeId,
pub name: String, pub name: String,
@ -319,7 +322,7 @@ pub struct VariableData {
/// Data for the use of some item (e.g., the use of a local variable, which /// Data for the use of some item (e.g., the use of a local variable, which
/// will refer to that variables declaration (by ref_id)). /// will refer to that variables declaration (by ref_id)).
#[derive(Debug)] #[derive(Debug, RustcEncodable)]
pub struct VariableRefData { pub struct VariableRefData {
pub name: String, pub name: String,
pub span: Span, pub span: Span,

View File

@ -8,33 +8,31 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use syntax::codemap::Span;
use super::data::*; use super::data::*;
pub trait Dump { pub trait Dump {
fn crate_prelude(&mut self, _: Span, _: CratePreludeData) {} fn crate_prelude(&mut self, CratePreludeData);
fn enum_data(&mut self, EnumData) {} fn enum_data(&mut self, EnumData);
fn extern_crate(&mut self, ExternCrateData) {} fn extern_crate(&mut self, ExternCrateData);
fn impl_data(&mut self, ImplData) {} fn impl_data(&mut self, ImplData);
fn inheritance(&mut self, InheritanceData) {} fn inheritance(&mut self, InheritanceData);
fn function(&mut self, FunctionData) {} fn function(&mut self, FunctionData);
fn function_ref(&mut self, FunctionRefData) {} fn function_ref(&mut self, FunctionRefData);
fn function_call(&mut self, FunctionCallData) {} fn function_call(&mut self, FunctionCallData);
fn method(&mut self, MethodData) {} fn method(&mut self, MethodData);
fn method_call(&mut self, MethodCallData) {} fn method_call(&mut self, MethodCallData);
fn macro_data(&mut self, MacroData) {} fn macro_data(&mut self, MacroData);
fn macro_use(&mut self, MacroUseData) {} fn macro_use(&mut self, MacroUseData);
fn mod_data(&mut self, ModData) {} fn mod_data(&mut self, ModData);
fn mod_ref(&mut self, ModRefData) {} fn mod_ref(&mut self, ModRefData);
fn struct_data(&mut self, StructData) {} fn struct_data(&mut self, StructData);
fn struct_variant(&mut self, StructVariantData) {} fn struct_variant(&mut self, StructVariantData);
fn trait_data(&mut self, TraitData) {} fn trait_data(&mut self, TraitData);
fn tuple_variant(&mut self, TupleVariantData) {} fn tuple_variant(&mut self, TupleVariantData);
fn type_ref(&mut self, TypeRefData) {} fn type_ref(&mut self, TypeRefData);
fn typedef(&mut self, TypedefData) {} fn typedef(&mut self, TypedefData);
fn use_data(&mut self, UseData) {} fn use_data(&mut self, UseData);
fn use_glob(&mut self, UseGlobData) {} fn use_glob(&mut self, UseGlobData);
fn variable(&mut self, VariableData) {} fn variable(&mut self, VariableData);
fn variable_ref(&mut self, VariableRefData) {} fn variable_ref(&mut self, VariableRefData);
} }

View File

@ -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. // Info about all the external crates referenced from this crate.
let external_crates = self.save_ctxt.get_external_crates().into_iter().map(|c| { 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 { ExternalCrateData {
name: c.name, name: c.name,
num: c.number num: c.number,
file_name: SpanUtils::make_path_string(&lo_loc.file.name),
} }
}).collect(); }).collect();
// The current crate. // The current crate.
let data = CratePreludeData { let data = CratePreludeData {
crate_name: name.into(), crate_name: name.into(),
crate_root: crate_root, crate_root: crate_root.unwrap_or("<no source>".to_owned()),
external_crates: external_crates 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. // Return all non-empty prefixes of a path.

View File

@ -0,0 +1,63 @@
// 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 super::data::*;
use super::dump::Dump;
pub struct JsonDumper<'b, W: 'b> {
output: &'b mut W,
}
impl<'b, W: Write> JsonDumper<'b, W> {
pub fn new(writer: &'b mut W) -> JsonDumper<'b, W> {
JsonDumper { output: writer }
}
}
macro_rules! impl_fn {
($fn_name: ident, $data_type: ident) => {
fn $fn_name(&mut self, data: $data_type) {
if let Err(_) = write!(self.output, "{}", as_json(&data)) {
error!("Error writing output '{}'", as_json(&data));
}
}
}
}
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);
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);
}

View File

@ -26,6 +26,7 @@
#[macro_use] extern crate log; #[macro_use] extern crate log;
#[macro_use] extern crate syntax; #[macro_use] extern crate syntax;
extern crate serialize as rustc_serialize;
use rustc::hir::{self, lowering}; use rustc::hir::{self, lowering};
use rustc::hir::map::NodeItem; use rustc::hir::map::NodeItem;
@ -45,6 +46,7 @@ use syntax::visit::{self, Visitor};
use syntax::print::pprust::ty_to_string; use syntax::print::pprust::ty_to_string;
mod csv_dumper; mod csv_dumper;
mod json_dumper;
mod data; mod data;
mod dump; mod dump;
mod dump_visitor; mod dump_visitor;
@ -52,6 +54,7 @@ mod dump_visitor;
pub mod span_utils; pub mod span_utils;
pub use self::csv_dumper::CsvDumper; pub use self::csv_dumper::CsvDumper;
pub use self::json_dumper::JsonDumper;
pub use self::data::*; pub use self::data::*;
pub use self::dump::Dump; pub use self::dump::Dump;
pub use self::dump_visitor::DumpVisitor; pub use self::dump_visitor::DumpVisitor;
@ -104,9 +107,17 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
let mut result = Vec::new(); let mut result = Vec::new();
for n in self.tcx.sess.cstore.crates() { 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 { result.push(CrateData {
name: (&self.tcx.sess.cstore.crate_name(n)[..]).to_owned(), name: (&self.tcx.sess.cstore.crate_name(n)[..]).to_owned(),
number: n, number: n,
span: span,
}); });
} }