diff --git a/mk/crates.mk b/mk/crates.mk index 02b95f5b1a9..fec9e985e04 100644 --- a/mk/crates.mk +++ b/mk/crates.mk @@ -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 diff --git a/src/librustc_save_analysis/Cargo.toml b/src/librustc_save_analysis/Cargo.toml index 52fa9193472..76f5569ecb6 100644 --- a/src/librustc_save_analysis/Cargo.toml +++ b/src/librustc_save_analysis/Cargo.toml @@ -12,3 +12,4 @@ crate-type = ["dylib"] log = { path = "../liblog" } rustc = { path = "../librustc" } syntax = { path = "../libsyntax" } +serialize = { path = "../librustc_serialize" } diff --git a/src/librustc_save_analysis/csv_dumper.rs b/src/librustc_save_analysis/csv_dumper.rs index 69de5365c14..4d6512db861 100644 --- a/src/librustc_save_analysis/csv_dumper.rs +++ b/src/librustc_save_analysis/csv_dumper.rs @@ -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> { - fn crate_prelude(&mut self, span: Span, data: CratePreludeData) { - let crate_root = data.crate_root.unwrap_or("".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)); diff --git a/src/librustc_save_analysis/data.rs b/src/librustc_save_analysis/data.rs index 7f2f2618c3c..2fbeac8be83 100644 --- a/src/librustc_save_analysis/data.rs +++ b/src/librustc_save_analysis/data.rs @@ -23,11 +23,12 @@ use syntax::codemap::Span; 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 +80,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, - pub external_crates: Vec + pub crate_root: String, + pub external_crates: Vec, + 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 +107,7 @@ pub struct EnumData { } /// Data for extern crates. -#[derive(Debug)] +#[derive(Debug, RustcEncodable)] pub struct ExternCrateData { pub id: NodeId, pub name: String, @@ -115,7 +118,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 +126,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 +137,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 +153,7 @@ pub struct ImplData { pub self_ref: Option, } -#[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 +167,7 @@ pub struct ImplData2 { pub self_ref: Option, } -#[derive(Debug)] +#[derive(Debug, RustcEncodable)] pub struct InheritanceData { pub span: Span, pub base_id: DefId, @@ -172,7 +175,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 +183,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 +196,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 +205,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 +214,7 @@ pub struct MethodData { } /// Data for modules. -#[derive(Debug)] +#[derive(Debug, RustcEncodable)] pub struct ModData { pub id: NodeId, pub name: String, @@ -222,7 +225,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 +233,7 @@ pub struct ModRefData { pub qualname: String } -#[derive(Debug)] +#[derive(Debug, RustcEncodable)] pub struct StructData { pub span: Span, pub id: NodeId, @@ -240,7 +243,7 @@ pub struct StructData { pub value: String } -#[derive(Debug)] +#[derive(Debug, RustcEncodable)] pub struct StructVariantData { pub span: Span, pub id: NodeId, @@ -250,7 +253,7 @@ pub struct StructVariantData { pub scope: NodeId } -#[derive(Debug)] +#[derive(Debug, RustcEncodable)] pub struct TraitData { pub span: Span, pub id: NodeId, @@ -259,7 +262,7 @@ pub struct TraitData { pub value: String } -#[derive(Debug)] +#[derive(Debug, RustcEncodable)] pub struct TupleVariantData { pub span: Span, pub id: NodeId, @@ -271,7 +274,7 @@ pub struct TupleVariantData { } /// Data for a typedef. -#[derive(Debug)] +#[derive(Debug, RustcEncodable)] pub struct TypedefData { pub id: NodeId, pub span: Span, @@ -280,7 +283,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 +291,7 @@ pub struct TypeRefData { pub qualname: String, } -#[derive(Debug)] +#[derive(Debug, RustcEncodable)] pub struct UseData { pub id: NodeId, pub span: Span, @@ -297,7 +300,7 @@ pub struct UseData { pub scope: NodeId } -#[derive(Debug)] +#[derive(Debug, RustcEncodable)] pub struct UseGlobData { pub id: NodeId, pub span: Span, @@ -306,7 +309,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 +322,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, diff --git a/src/librustc_save_analysis/dump.rs b/src/librustc_save_analysis/dump.rs index 69efa74c582..feb428b0746 100644 --- a/src/librustc_save_analysis/dump.rs +++ b/src/librustc_save_analysis/dump.rs @@ -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, 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) {} + 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); } diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index c6513a8288b..a4efb68e63c 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -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("".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. diff --git a/src/librustc_save_analysis/json_dumper.rs b/src/librustc_save_analysis/json_dumper.rs new file mode 100644 index 00000000000..8a631ad8b32 --- /dev/null +++ b/src/librustc_save_analysis/json_dumper.rs @@ -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 or the MIT license +// , 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); +} diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 9148b53322b..db7a7a64998 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -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, }); }