From cbafc5758ba905e57d3f10476deb05a79588cd81 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 29 Aug 2016 12:24:55 +1200 Subject: [PATCH 1/5] save-analsysis: add save-analysis-api CLI flag --- src/librustc/session/config.rs | 10 ++++++++-- src/librustc_driver/lib.rs | 5 ++++- src/librustc_save_analysis/lib.rs | 4 +++- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 562dce6a1b129..8eb80472d6e09 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -848,9 +848,13 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, ls: bool = (false, parse_bool, [UNTRACKED], "list the symbols defined by a library crate"), save_analysis: bool = (false, parse_bool, [UNTRACKED], - "write syntax and type analysis (in JSON format) information in addition to normal output"), + "write syntax and type analysis (in JSON format) information, \ + addition to normal output"), save_analysis_csv: bool = (false, parse_bool, [UNTRACKED], - "write syntax and type analysis (in CSV format) information in addition to normal output"), + "write syntax and type analysis (in CSV format) information, in addition to normal output"), + save_analysis_api: bool = (false, parse_bool, [UNTRACKED], + "write syntax and type analysis information for opaque libraries (in JSON format), \ + in addition to normal output"), print_move_fragments: bool = (false, parse_bool, [UNTRACKED], "print out move-fragment data for every fn"), flowgraph_print_loans: bool = (false, parse_bool, [UNTRACKED], @@ -2359,6 +2363,8 @@ mod tests { assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); opts.debugging_opts.save_analysis_csv = true; assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); + opts.debugging_opts.save_analysis_api = true; + assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); opts.debugging_opts.print_move_fragments = true; assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); opts.debugging_opts.flowgraph_print_loans = true; diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index efadf1ff488df..95f8aa620a91a 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -555,7 +555,8 @@ 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 + sess.opts.debugging_opts.save_analysis_csv || + sess.opts.debugging_opts.save_analysis_api } fn save_analysis_format(sess: &Session) -> save::Format { @@ -563,6 +564,8 @@ fn save_analysis_format(sess: &Session) -> save::Format { save::Format::Json } else if sess.opts.debugging_opts.save_analysis_csv { save::Format::Csv + } else if sess.opts.debugging_opts.save_analysis_api { + save::Format::JsonApi } else { unreachable!(); } diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index db535e22f194d..77273bd3f2ed2 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -727,13 +727,14 @@ impl Visitor for PathCollector { pub enum Format { Csv, Json, + JsonApi, } impl Format { fn extension(&self) -> &'static str { match *self { Format::Csv => ".csv", - Format::Json => ".json", + Format::Json | Format::JsonApi => ".json", } } } @@ -803,6 +804,7 @@ pub fn process_crate<'l, 'tcx>(tcx: TyCtxt<'l, 'tcx, 'tcx>, match format { Format::Csv => dump!(CsvDumper::new(output)), Format::Json => dump!(JsonDumper::new(output)), + Format::JsonApi => /* TODO */ dump!(JsonDumper::new(output)), } } From c7dfc89f854f629816253f84ac0cc15d7792d63f Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 29 Aug 2016 13:29:12 +1200 Subject: [PATCH 2/5] JsonApiDumper --- src/librustc_save_analysis/json_api_dumper.rs | 356 ++++++++++++++++++ src/librustc_save_analysis/lib.rs | 4 +- 2 files changed, 359 insertions(+), 1 deletion(-) create mode 100644 src/librustc_save_analysis/json_api_dumper.rs diff --git a/src/librustc_save_analysis/json_api_dumper.rs b/src/librustc_save_analysis/json_api_dumper.rs new file mode 100644 index 0000000000000..e92c23d7d7c5a --- /dev/null +++ b/src/librustc_save_analysis/json_api_dumper.rs @@ -0,0 +1,356 @@ +// 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::hir::def_id::DefId; +use rustc_serialize::json::as_json; + +use external_data::*; +use data::VariableKind; +use dump::Dump; + +pub struct JsonApiDumper<'b, W: Write + 'b> { + output: &'b mut W, + result: Analysis, +} + +impl<'b, W: Write> JsonApiDumper<'b, W> { + pub fn new(writer: &'b mut W) -> JsonApiDumper<'b, W> { + JsonApiDumper { output: writer, result: Analysis::new() } + } +} + +impl<'b, W: Write> Drop for JsonApiDumper<'b, W> { + fn drop(&mut self) { + if let Err(_) = write!(self.output, "{}", as_json(&self.result)) { + error!("Error writing output"); + } + } +} + +macro_rules! impl_fn { + ($fn_name: ident, $data_type: ident, $bucket: ident) => { + fn $fn_name(&mut self, data: $data_type) { + if let Some(datum) = From::from(data) { + self.result.$bucket.push(datum); + } + } + } +} + +impl<'b, W: Write + 'b> Dump for JsonApiDumper<'b, W> { + fn crate_prelude(&mut self, data: CratePreludeData) { + self.result.prelude = Some(data) + } + + impl_fn!(use_data, UseData, imports); + impl_fn!(use_glob, UseGlobData, imports); + + impl_fn!(enum_data, EnumData, defs); + impl_fn!(tuple_variant, TupleVariantData, defs); + impl_fn!(struct_variant, StructVariantData, defs); + impl_fn!(struct_data, StructData, defs); + impl_fn!(trait_data, TraitData, defs); + impl_fn!(function, FunctionData, defs); + impl_fn!(method, MethodData, defs); + impl_fn!(macro_data, MacroData, defs); + impl_fn!(mod_data, ModData, defs); + impl_fn!(typedef, TypeDefData, defs); + impl_fn!(variable, VariableData, defs); +} + +// FIXME methods. The defs have information about possible overriding and the +// refs have decl information (e.g., a trait method where we know the required +// method, but not the supplied method). In both cases, we are currently +// ignoring it. + +#[derive(Debug, RustcEncodable)] +struct Analysis { + prelude: Option, + imports: Vec, + defs: Vec, +} + +impl Analysis { + fn new() -> Analysis { + Analysis { + prelude: None, + imports: vec![], + defs: vec![], + } + } +} + +// DefId::index is a newtype and so the JSON serialisation is ugly. Therefore +// we use our own Id which is the same, but without the newtype. +#[derive(Debug, RustcEncodable)] +struct Id { + krate: u32, + index: u32, +} + +impl From for Id { + fn from(id: DefId) -> Id { + Id { + krate: id.krate, + index: id.index.as_u32(), + } + } +} + +#[derive(Debug, RustcEncodable)] +struct Import { + kind: ImportKind, + id: Id, + span: SpanData, + name: String, + value: String, +} + +#[derive(Debug, RustcEncodable)] +enum ImportKind { + Use, + GlobUse, +} + +impl From for Option { + fn from(data: UseData) -> Option { + Some(Import { + kind: ImportKind::Use, + id: From::from(data.id), + span: data.span, + name: data.name, + value: String::new(), + }) + } +} +impl From for Option { + fn from(data: UseGlobData) -> Option { + Some(Import { + kind: ImportKind::GlobUse, + id: From::from(data.id), + span: data.span, + name: "*".to_owned(), + value: data.names.join(", "), + }) + } +} + +#[derive(Debug, RustcEncodable)] +struct Def { + kind: DefKind, + id: Id, + span: SpanData, + name: String, + qualname: String, + value: String, + parent: Option, + children: Vec, + decl_id: Option, +} + +#[derive(Debug, RustcEncodable)] +enum DefKind { + // value = variant names + Enum, + // value = enum name + variant name + types + Tuple, + // value = [enum name +] name + fields + Struct, + // value = signature + Trait, + // value = type + generics + Function, + // value = type + generics + Method, + // No id, no value. + Macro, + // value = file_name + Mod, + // value = aliased type + Type, + // value = type and init expression (for all variable kinds). + Static, + Const, + Field, +} + +impl From for Option { + fn from(data: EnumData) -> Option { + Some(Def { + kind: DefKind::Enum, + id: From::from(data.id), + span: data.span, + name: data.name, + qualname: data.qualname, + value: data.value, + parent: None, + children: data.variants.into_iter().map(|id| From::from(id)).collect(), + decl_id: None, + }) + } +} + +impl From for Option { + fn from(data: TupleVariantData) -> Option { + Some(Def { + kind: DefKind::Tuple, + id: From::from(data.id), + span: data.span, + name: data.name, + qualname: data.qualname, + value: data.value, + parent: None, + children: vec![], + decl_id: None, + }) + } +} +impl From for Option { + fn from(data: StructVariantData) -> Option { + Some(Def { + kind: DefKind::Struct, + id: From::from(data.id), + span: data.span, + name: data.name, + qualname: data.qualname, + value: data.value, + parent: None, + children: vec![], + decl_id: None, + }) + } +} +impl From for Option { + fn from(data: StructData) -> Option { + Some(Def { + kind: DefKind::Struct, + id: From::from(data.id), + span: data.span, + name: data.name, + qualname: data.qualname, + value: data.value, + parent: None, + children: data.fields.into_iter().map(|id| From::from(id)).collect(), + decl_id: None, + }) + } +} +impl From for Option { + fn from(data: TraitData) -> Option { + Some(Def { + kind: DefKind::Trait, + id: From::from(data.id), + span: data.span, + name: data.name, + qualname: data.qualname, + value: data.value, + children: data.items.into_iter().map(|id| From::from(id)).collect(), + parent: None, + decl_id: None, + }) + } +} +impl From for Option { + fn from(data: FunctionData) -> Option { + Some(Def { + kind: DefKind::Function, + id: From::from(data.id), + span: data.span, + name: data.name, + qualname: data.qualname, + value: data.value, + children: vec![], + parent: None, + decl_id: None, + }) + } +} +impl From for Option { + fn from(data: MethodData) -> Option { + Some(Def { + kind: DefKind::Method, + id: From::from(data.id), + span: data.span, + name: data.name, + qualname: data.qualname, + value: data.value, + children: vec![], + parent: None, + decl_id: data.decl_id.map(|id| From::from(id)), + }) + } +} +impl From for Option { + fn from(data: MacroData) -> Option { + Some(Def { + kind: DefKind::Macro, + id: From::from(null_def_id()), + span: data.span, + name: data.name, + qualname: data.qualname, + value: String::new(), + children: vec![], + parent: None, + decl_id: None, + }) + } +} +impl From for Option { + fn from(data:ModData) -> Option { + Some(Def { + kind: DefKind::Mod, + id: From::from(data.id), + span: data.span, + name: data.name, + qualname: data.qualname, + value: data.filename, + children: data.items.into_iter().map(|id| From::from(id)).collect(), + parent: None, + decl_id: None, + }) + } +} +impl From for Option { + fn from(data: TypeDefData) -> Option { + Some(Def { + kind: DefKind::Type, + id: From::from(data.id), + span: data.span, + name: data.name, + qualname: data.qualname, + value: data.value, + children: vec![], + parent: None, + decl_id: None, + }) + } +} +impl From for Option { + fn from(data: VariableData) -> Option { + Some(Def { + kind: match data.kind { + VariableKind::Static => DefKind::Static, + VariableKind::Const => DefKind::Const, + VariableKind::Local => { return None } + VariableKind::Field => DefKind::Field, + }, + id: From::from(data.id), + span: data.span, + name: data.name, + qualname: data.qualname, + value: data.value, + children: vec![], + parent: None, + decl_id: None, + }) + } +} diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 77273bd3f2ed2..5aa8bec3d36c2 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -30,6 +30,7 @@ extern crate serialize as rustc_serialize; extern crate syntax_pos; mod csv_dumper; +mod json_api_dumper; mod json_dumper; mod data; mod dump; @@ -57,6 +58,7 @@ use syntax::codemap::MacroAttribute; use syntax_pos::*; pub use self::csv_dumper::CsvDumper; +pub use self::json_api_dumper::JsonApiDumper; pub use self::json_dumper::JsonDumper; pub use self::data::*; pub use self::dump::Dump; @@ -804,7 +806,7 @@ pub fn process_crate<'l, 'tcx>(tcx: TyCtxt<'l, 'tcx, 'tcx>, match format { Format::Csv => dump!(CsvDumper::new(output)), Format::Json => dump!(JsonDumper::new(output)), - Format::JsonApi => /* TODO */ dump!(JsonDumper::new(output)), + Format::JsonApi => dump!(JsonApiDumper::new(output)), } } From 4e4306c6dfa7a8dd43a7ee9bbc531f4b14b03aec Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 29 Aug 2016 16:46:55 +1200 Subject: [PATCH 3/5] Thread visibility info through save-analysis and filter save-analysis-api on it. --- src/librustc_save_analysis/data.rs | 47 +++- src/librustc_save_analysis/dump_visitor.rs | 39 ++- src/librustc_save_analysis/external_data.rs | 28 ++- src/librustc_save_analysis/json_api_dumper.rs | 228 ++++++++++-------- src/librustc_save_analysis/lib.rs | 15 +- 5 files changed, 235 insertions(+), 122 deletions(-) diff --git a/src/librustc_save_analysis/data.rs b/src/librustc_save_analysis/data.rs index 493f7669337fe..b882765788893 100644 --- a/src/librustc_save_analysis/data.rs +++ b/src/librustc_save_analysis/data.rs @@ -13,8 +13,9 @@ //! The `Dump` trait can be used together with `DumpVisitor` in order to //! retrieve the data from a crate. +use rustc::hir; use rustc::hir::def_id::DefId; -use syntax::ast::{CrateNum, NodeId}; +use syntax::ast::{self, CrateNum, NodeId}; use syntax_pos::Span; pub struct CrateData { @@ -76,6 +77,35 @@ pub enum Data { VariableRefData(VariableRefData), } +#[derive(Eq, PartialEq, Clone, Copy, Debug, RustcEncodable)] +pub enum Visibility { + Public, + Restricted, + Inherited, +} + +impl<'a> From<&'a ast::Visibility> for Visibility { + fn from(v: &'a ast::Visibility) -> Visibility { + match *v { + ast::Visibility::Public => Visibility::Public, + ast::Visibility::Crate(_) => Visibility::Restricted, + ast::Visibility::Restricted { .. } => Visibility::Restricted, + ast::Visibility::Inherited => Visibility::Inherited, + } + } +} + +impl<'a> From<&'a hir::Visibility> for Visibility { + fn from(v: &'a hir::Visibility) -> Visibility { + match *v { + hir::Visibility::Public => Visibility::Public, + hir::Visibility::Crate => Visibility::Restricted, + hir::Visibility::Restricted { .. } => Visibility::Restricted, + hir::Visibility::Inherited => Visibility::Inherited, + } + } +} + /// Data for the prelude of a crate. #[derive(Debug, RustcEncodable)] pub struct CratePreludeData { @@ -103,7 +133,7 @@ pub struct EnumData { pub span: Span, pub scope: NodeId, pub variants: Vec, - + pub visibility: Visibility, } /// Data for extern crates. @@ -135,6 +165,7 @@ pub struct FunctionData { pub span: Span, pub scope: NodeId, pub value: String, + pub visibility: Visibility, } /// Data about a function call. @@ -215,6 +246,7 @@ pub struct MethodData { pub scope: NodeId, pub value: String, pub decl_id: Option, + pub visibility: Visibility, } /// Data for modules. @@ -227,6 +259,7 @@ pub struct ModData { pub scope: NodeId, pub filename: String, pub items: Vec, + pub visibility: Visibility, } /// Data for a reference to a module. @@ -248,6 +281,7 @@ pub struct StructData { pub scope: NodeId, pub value: String, pub fields: Vec, + pub visibility: Visibility, } #[derive(Debug, RustcEncodable)] @@ -270,6 +304,7 @@ pub struct TraitData { pub scope: NodeId, pub value: String, pub items: Vec, + pub visibility: Visibility, } #[derive(Debug, RustcEncodable)] @@ -291,6 +326,7 @@ pub struct TypeDefData { pub span: Span, pub qualname: String, pub value: String, + pub visibility: Visibility, } /// Data for a reference to a type or trait. @@ -308,7 +344,8 @@ pub struct UseData { pub span: Span, pub name: String, pub mod_id: Option, - pub scope: NodeId + pub scope: NodeId, + pub visibility: Visibility, } #[derive(Debug, RustcEncodable)] @@ -316,7 +353,8 @@ pub struct UseGlobData { pub id: NodeId, pub span: Span, pub names: Vec, - pub scope: NodeId + pub scope: NodeId, + pub visibility: Visibility, } /// Data for local and global variables (consts and statics). @@ -330,6 +368,7 @@ pub struct VariableData { pub scope: NodeId, pub value: String, pub type_value: String, + pub visibility: Visibility, } #[derive(Debug, RustcEncodable)] diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index dbe956f021e4c..e0475bfed931a 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -364,7 +364,8 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { qualname: format!("{}::{}", qualname, path_to_string(p)), type_value: typ, value: String::new(), - scope: 0 + scope: 0, + visibility: Visibility::Inherited, }.lower(self.tcx)); } } @@ -376,6 +377,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { body: Option<&ast::Block>, id: ast::NodeId, name: ast::Name, + vis: Visibility, span: Span) { debug!("process_method: {}:{}", id, name); @@ -416,6 +418,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { qualname: method_data.qualname.clone(), value: sig_str, decl_id: decl_id, + visibility: vis, }.lower(self.tcx)); } @@ -483,7 +486,8 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { name: name, id: param.id, qualname: qualname, - value: String::new() + value: String::new(), + visibility: Visibility::Inherited, }.lower(self.tcx)); } } @@ -532,7 +536,8 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { name: ast::Name, span: Span, typ: &ast::Ty, - expr: &ast::Expr) { + expr: &ast::Expr, + vis: Visibility) { let qualname = format!("::{}", self.tcx.node_path_str(id)); let sub_span = self.span.sub_span_after_keyword(span, keywords::Const); @@ -546,7 +551,8 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { qualname: qualname, value: self.span.snippet(expr.span), type_value: ty_to_string(&typ), - scope: self.cur_scope + scope: self.cur_scope, + visibility: vis, }.lower(self.tcx)); } @@ -588,6 +594,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { scope: self.cur_scope, value: val, fields: fields, + visibility: From::from(&item.vis), }.lower(self.tcx)); } @@ -744,6 +751,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { scope: self.cur_scope, value: val, items: methods.iter().map(|i| i.id).collect(), + visibility: From::from(&item.vis), }.lower(self.tcx)); } @@ -989,7 +997,8 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { qualname: format!("{}${}", path_to_string(p), id), value: value, type_value: typ, - scope: 0 + scope: 0, + visibility: Visibility::Inherited, }.lower(self.tcx)); } } @@ -1072,7 +1081,8 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor for DumpVisitor<'l, 'tcx, 'll, D> id: item.id, mod_id: mod_id, name: ident.to_string(), - scope: self.cur_scope + scope: self.cur_scope, + visibility: From::from(&item.vis), }.lower(self.tcx)); } self.write_sub_paths_truncated(path, true); @@ -1095,7 +1105,8 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor for DumpVisitor<'l, 'tcx, 'll, D> span: sub_span.expect("No span found for use glob"), id: item.id, names: names, - scope: self.cur_scope + scope: self.cur_scope, + visibility: From::from(&item.vis), }.lower(self.tcx)); } self.write_sub_paths(path, true); @@ -1167,7 +1178,8 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor for DumpVisitor<'l, 'tcx, 'll, D> name: item.ident.to_string(), id: item.id, qualname: qualname.clone(), - value: value + value: value, + visibility: From::from(&item.vis), }.lower(self.tcx)); } @@ -1200,13 +1212,15 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor for DumpVisitor<'l, 'tcx, 'll, D> trait_item.ident.name, trait_item.span, &ty, - &expr); + &expr, + Visibility::Public); } ast::TraitItemKind::Method(ref sig, ref body) => { self.process_method(sig, body.as_ref().map(|x| &**x), trait_item.id, trait_item.ident.name, + Visibility::Public, trait_item.span); } ast::TraitItemKind::Const(_, None) | @@ -1223,13 +1237,15 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor for DumpVisitor<'l, 'tcx, 'll, D> impl_item.ident.name, impl_item.span, &ty, - &expr); + &expr, + From::from(&impl_item.vis)); } ast::ImplItemKind::Method(ref sig, ref body) => { self.process_method(sig, Some(body), impl_item.id, impl_item.ident.name, + From::from(&impl_item.vis), impl_item.span); } ast::ImplItemKind::Type(_) | @@ -1399,7 +1415,8 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor for DumpVisitor<'l, 'tcx, 'll, D> qualname: format!("{}${}", path_to_string(p), id), value: value, type_value: String::new(), - scope: 0 + scope: 0, + visibility: Visibility::Inherited, }.lower(self.tcx)); } } diff --git a/src/librustc_save_analysis/external_data.rs b/src/librustc_save_analysis/external_data.rs index 65e4f7e869b0d..b7dded7b6247b 100644 --- a/src/librustc_save_analysis/external_data.rs +++ b/src/librustc_save_analysis/external_data.rs @@ -15,7 +15,7 @@ use syntax::ast::{CrateNum, NodeId}; use syntax::codemap::CodeMap; use syntax_pos::Span; -use data; +use data::{self, Visibility}; // FIXME: this should be pub(crate), but the current snapshot doesn't allow it yet pub trait Lower { @@ -91,7 +91,8 @@ pub struct EnumData { pub qualname: String, pub span: SpanData, pub scope: DefId, - pub variants: Vec + pub variants: Vec, + pub visibility: Visibility, } impl Lower for data::EnumData { @@ -106,6 +107,7 @@ impl Lower for data::EnumData { span: SpanData::from_span(self.span, tcx.sess.codemap()), scope: make_def_id(self.scope, &tcx.map), variants: self.variants.into_iter().map(|id| make_def_id(id, &tcx.map)).collect(), + visibility: self.visibility, } } } @@ -166,6 +168,7 @@ pub struct FunctionData { pub span: SpanData, pub scope: DefId, pub value: String, + pub visibility: Visibility, } impl Lower for data::FunctionData { @@ -180,6 +183,7 @@ impl Lower for data::FunctionData { span: SpanData::from_span(self.span, tcx.sess.codemap()), scope: make_def_id(self.scope, &tcx.map), value: self.value, + visibility: self.visibility, } } } @@ -323,6 +327,7 @@ pub struct MethodData { pub scope: DefId, pub value: String, pub decl_id: Option, + pub visibility: Visibility, } impl Lower for data::MethodData { @@ -337,6 +342,7 @@ impl Lower for data::MethodData { qualname: self.qualname, value: self.value, decl_id: self.decl_id, + visibility: self.visibility, } } } @@ -351,6 +357,7 @@ pub struct ModData { pub scope: DefId, pub filename: String, pub items: Vec, + pub visibility: Visibility, } impl Lower for data::ModData { @@ -365,6 +372,7 @@ impl Lower for data::ModData { scope: make_def_id(self.scope, &tcx.map), filename: self.filename, items: self.items.into_iter().map(|id| make_def_id(id, &tcx.map)).collect(), + visibility: self.visibility, } } } @@ -401,6 +409,7 @@ pub struct StructData { pub scope: DefId, pub value: String, pub fields: Vec, + pub visibility: Visibility, } impl Lower for data::StructData { @@ -416,6 +425,7 @@ impl Lower for data::StructData { scope: make_def_id(self.scope, &tcx.map), value: self.value, fields: self.fields.into_iter().map(|id| make_def_id(id, &tcx.map)).collect(), + visibility: self.visibility, } } } @@ -456,6 +466,7 @@ pub struct TraitData { pub scope: DefId, pub value: String, pub items: Vec, + pub visibility: Visibility, } impl Lower for data::TraitData { @@ -470,6 +481,7 @@ impl Lower for data::TraitData { scope: make_def_id(self.scope, &tcx.map), value: self.value, items: self.items.into_iter().map(|id| make_def_id(id, &tcx.map)).collect(), + visibility: self.visibility, } } } @@ -509,6 +521,7 @@ pub struct TypeDefData { pub span: SpanData, pub qualname: String, pub value: String, + pub visibility: Visibility, } impl Lower for data::TypeDefData { @@ -521,6 +534,7 @@ impl Lower for data::TypeDefData { span: SpanData::from_span(self.span, tcx.sess.codemap()), qualname: self.qualname, value: self.value, + visibility: self.visibility, } } } @@ -553,7 +567,8 @@ pub struct UseData { pub span: SpanData, pub name: String, pub mod_id: Option, - pub scope: DefId + pub scope: DefId, + pub visibility: Visibility, } impl Lower for data::UseData { @@ -566,6 +581,7 @@ impl Lower for data::UseData { name: self.name, mod_id: self.mod_id, scope: make_def_id(self.scope, &tcx.map), + visibility: self.visibility, } } } @@ -575,7 +591,8 @@ pub struct UseGlobData { pub id: DefId, pub span: SpanData, pub names: Vec, - pub scope: DefId + pub scope: DefId, + pub visibility: Visibility, } impl Lower for data::UseGlobData { @@ -587,6 +604,7 @@ impl Lower for data::UseGlobData { span: SpanData::from_span(self.span, tcx.sess.codemap()), names: self.names, scope: make_def_id(self.scope, &tcx.map), + visibility: self.visibility, } } } @@ -602,6 +620,7 @@ pub struct VariableData { pub scope: DefId, pub value: String, pub type_value: String, + pub visibility: Visibility, } impl Lower for data::VariableData { @@ -617,6 +636,7 @@ impl Lower for data::VariableData { scope: make_def_id(self.scope, &tcx.map), value: self.value, type_value: self.type_value, + visibility: self.visibility, } } } diff --git a/src/librustc_save_analysis/json_api_dumper.rs b/src/librustc_save_analysis/json_api_dumper.rs index e92c23d7d7c5a..9cc1badf7cdd9 100644 --- a/src/librustc_save_analysis/json_api_dumper.rs +++ b/src/librustc_save_analysis/json_api_dumper.rs @@ -14,7 +14,7 @@ use rustc::hir::def_id::DefId; use rustc_serialize::json::as_json; use external_data::*; -use data::VariableKind; +use data::{VariableKind, Visibility}; use dump::Dump; pub struct JsonApiDumper<'b, W: Write + 'b> { @@ -123,24 +123,30 @@ enum ImportKind { impl From for Option { fn from(data: UseData) -> Option { - Some(Import { - kind: ImportKind::Use, - id: From::from(data.id), - span: data.span, - name: data.name, - value: String::new(), - }) + match data.visibility { + Visibility::Public => Some(Import { + kind: ImportKind::Use, + id: From::from(data.id), + span: data.span, + name: data.name, + value: String::new(), + }), + _ => None, + } } } impl From for Option { fn from(data: UseGlobData) -> Option { - Some(Import { - kind: ImportKind::GlobUse, - id: From::from(data.id), - span: data.span, - name: "*".to_owned(), - value: data.names.join(", "), - }) + match data.visibility { + Visibility::Public => Some(Import { + kind: ImportKind::GlobUse, + id: From::from(data.id), + span: data.span, + name: "*".to_owned(), + value: data.names.join(", "), + }), + _ => None, + } } } @@ -185,17 +191,20 @@ enum DefKind { impl From for Option { fn from(data: EnumData) -> Option { - Some(Def { - kind: DefKind::Enum, - id: From::from(data.id), - span: data.span, - name: data.name, - qualname: data.qualname, - value: data.value, - parent: None, - children: data.variants.into_iter().map(|id| From::from(id)).collect(), - decl_id: None, - }) + match data.visibility { + Visibility::Public => Some(Def { + kind: DefKind::Enum, + id: From::from(data.id), + span: data.span, + name: data.name, + qualname: data.qualname, + value: data.value, + parent: None, + children: data.variants.into_iter().map(|id| From::from(id)).collect(), + decl_id: None, + }), + _ => None, + } } } @@ -231,7 +240,8 @@ impl From for Option { } impl From for Option { fn from(data: StructData) -> Option { - Some(Def { + match data.visibility { + Visibility::Public => Some(Def { kind: DefKind::Struct, id: From::from(data.id), span: data.span, @@ -241,52 +251,63 @@ impl From for Option { parent: None, children: data.fields.into_iter().map(|id| From::from(id)).collect(), decl_id: None, - }) + }), + _ => None, + } } } impl From for Option { fn from(data: TraitData) -> Option { - Some(Def { - kind: DefKind::Trait, - id: From::from(data.id), - span: data.span, - name: data.name, - qualname: data.qualname, - value: data.value, - children: data.items.into_iter().map(|id| From::from(id)).collect(), - parent: None, - decl_id: None, - }) + match data.visibility { + Visibility::Public => Some(Def { + kind: DefKind::Trait, + id: From::from(data.id), + span: data.span, + name: data.name, + qualname: data.qualname, + value: data.value, + children: data.items.into_iter().map(|id| From::from(id)).collect(), + parent: None, + decl_id: None, + }), + _ => None, + } } } impl From for Option { fn from(data: FunctionData) -> Option { - Some(Def { - kind: DefKind::Function, - id: From::from(data.id), - span: data.span, - name: data.name, - qualname: data.qualname, - value: data.value, - children: vec![], - parent: None, - decl_id: None, - }) + match data.visibility { + Visibility::Public => Some(Def { + kind: DefKind::Function, + id: From::from(data.id), + span: data.span, + name: data.name, + qualname: data.qualname, + value: data.value, + children: vec![], + parent: None, + decl_id: None, + }), + _ => None, + } } } impl From for Option { fn from(data: MethodData) -> Option { - Some(Def { - kind: DefKind::Method, - id: From::from(data.id), - span: data.span, - name: data.name, - qualname: data.qualname, - value: data.value, - children: vec![], - parent: None, - decl_id: data.decl_id.map(|id| From::from(id)), - }) + match data.visibility { + Visibility::Public => Some(Def { + kind: DefKind::Method, + id: From::from(data.id), + span: data.span, + name: data.name, + qualname: data.qualname, + value: data.value, + children: vec![], + parent: None, + decl_id: data.decl_id.map(|id| From::from(id)), + }), + _ => None, + } } } impl From for Option { @@ -306,51 +327,60 @@ impl From for Option { } impl From for Option { fn from(data:ModData) -> Option { - Some(Def { - kind: DefKind::Mod, - id: From::from(data.id), - span: data.span, - name: data.name, - qualname: data.qualname, - value: data.filename, - children: data.items.into_iter().map(|id| From::from(id)).collect(), - parent: None, - decl_id: None, - }) + match data.visibility { + Visibility::Public => Some(Def { + kind: DefKind::Mod, + id: From::from(data.id), + span: data.span, + name: data.name, + qualname: data.qualname, + value: data.filename, + children: data.items.into_iter().map(|id| From::from(id)).collect(), + parent: None, + decl_id: None, + }), + _ => None, + } } } impl From for Option { fn from(data: TypeDefData) -> Option { - Some(Def { - kind: DefKind::Type, - id: From::from(data.id), - span: data.span, - name: data.name, - qualname: data.qualname, - value: data.value, - children: vec![], - parent: None, - decl_id: None, - }) + match data.visibility { + Visibility::Public => Some(Def { + kind: DefKind::Type, + id: From::from(data.id), + span: data.span, + name: data.name, + qualname: data.qualname, + value: data.value, + children: vec![], + parent: None, + decl_id: None, + }), + _ => None, + } } } impl From for Option { fn from(data: VariableData) -> Option { - Some(Def { - kind: match data.kind { - VariableKind::Static => DefKind::Static, - VariableKind::Const => DefKind::Const, - VariableKind::Local => { return None } - VariableKind::Field => DefKind::Field, - }, - id: From::from(data.id), - span: data.span, - name: data.name, - qualname: data.qualname, - value: data.value, - children: vec![], - parent: None, - decl_id: None, - }) + match data.visibility { + Visibility::Public => Some(Def { + kind: match data.kind { + VariableKind::Static => DefKind::Static, + VariableKind::Const => DefKind::Const, + VariableKind::Local => { return None } + VariableKind::Field => DefKind::Field, + }, + id: From::from(data.id), + span: data.span, + name: data.name, + qualname: data.qualname, + value: data.value, + children: vec![], + parent: None, + decl_id: None, + }), + _ => None, + } } } diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 5aa8bec3d36c2..3645eb68394d9 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -140,6 +140,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { span: sub_span.unwrap(), scope: self.enclosing_scope(item.id), value: make_signature(decl, generics), + visibility: From::from(&item.vis), })) } ast::ItemKind::Static(ref typ, mt, ref expr) => { @@ -164,6 +165,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { scope: self.enclosing_scope(item.id), value: value, type_value: ty_to_string(&typ), + visibility: From::from(&item.vis), })) } ast::ItemKind::Const(ref typ, ref expr) => { @@ -179,6 +181,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { scope: self.enclosing_scope(item.id), value: self.span_utils.snippet(expr.span), type_value: ty_to_string(&typ), + visibility: From::from(&item.vis), })) } ast::ItemKind::Mod(ref m) => { @@ -197,6 +200,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { scope: self.enclosing_scope(item.id), filename: filename, items: m.items.iter().map(|i| i.id).collect(), + visibility: From::from(&item.vis), })) } ast::ItemKind::Enum(ref def, _) => { @@ -217,6 +221,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { qualname: qualname, scope: self.enclosing_scope(item.id), variants: def.variants.iter().map(|v| v.node.data.id()).collect(), + visibility: From::from(&item.vis), })) } ast::ItemKind::Impl(_, _, _, ref trait_ref, ref typ, _) => { @@ -281,6 +286,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { scope: scope, value: "".to_owned(), type_value: typ, + visibility: From::from(&field.vis), }) } else { None @@ -293,7 +299,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { name: ast::Name, span: Span) -> Option { // The qualname for a method is the trait name or name of the struct in an impl in // which the method is declared in, followed by the method's name. - let qualname = match self.tcx.impl_of_method(self.tcx.map.local_def_id(id)) { + let (qualname, vis) = match self.tcx.impl_of_method(self.tcx.map.local_def_id(id)) { Some(impl_id) => match self.tcx.map.get_if_local(impl_id) { Some(NodeItem(item)) => { match item.node { @@ -306,7 +312,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { result.push_str(&self.tcx.item_path_str(def_id)); } result.push_str(">"); - result + (result, From::from(&item.vis)) } _ => { span_bug!(span, @@ -327,8 +333,8 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { None => match self.tcx.trait_of_item(self.tcx.map.local_def_id(id)) { Some(def_id) => { match self.tcx.map.get_if_local(def_id) { - Some(NodeItem(_)) => { - format!("::{}", self.tcx.item_path_str(def_id)) + Some(NodeItem(item)) => { + (format!("::{}", self.tcx.item_path_str(def_id)), From::from(&item.vis)) } r => { span_bug!(span, @@ -369,6 +375,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { scope: self.enclosing_scope(id), // FIXME you get better data here by using the visitor. value: String::new(), + visibility: vis, }) } From 4dc7b585a2d7784e5c8a8e390c77441df4aea29b Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 30 Aug 2016 16:00:48 +1200 Subject: [PATCH 4/5] save-analysis: add parent info to api dumps The parent id is used for constructing rustdoc URLs by clients --- src/librustc_driver/driver.rs | 3 +- src/librustc_save_analysis/data.rs | 9 +- src/librustc_save_analysis/dump_visitor.rs | 131 ++++++++++-------- src/librustc_save_analysis/external_data.rs | 14 +- src/librustc_save_analysis/json_api_dumper.rs | 19 ++- src/librustc_save_analysis/lib.rs | 6 + src/test/run-make/save-analysis/Makefile | 1 + 7 files changed, 113 insertions(+), 70 deletions(-) diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 94092be4922b5..df1378f9e0d0a 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -248,7 +248,8 @@ fn keep_hygiene_data(sess: &Session) -> bool { 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 + sess.opts.debugging_opts.save_analysis_csv || + sess.opts.debugging_opts.save_analysis_api } /// The name used for source code that doesn't originate in a file diff --git a/src/librustc_save_analysis/data.rs b/src/librustc_save_analysis/data.rs index b882765788893..a58cce0745f30 100644 --- a/src/librustc_save_analysis/data.rs +++ b/src/librustc_save_analysis/data.rs @@ -166,6 +166,7 @@ pub struct FunctionData { pub scope: NodeId, pub value: String, pub visibility: Visibility, + pub parent: Option, } /// Data about a function call. @@ -292,7 +293,8 @@ pub struct StructVariantData { pub qualname: String, pub type_value: String, pub value: String, - pub scope: NodeId + pub scope: NodeId, + pub parent: Option, } #[derive(Debug, RustcEncodable)] @@ -315,7 +317,8 @@ pub struct TupleVariantData { pub qualname: String, pub type_value: String, pub value: String, - pub scope: NodeId + pub scope: NodeId, + pub parent: Option, } /// Data for a typedef. @@ -327,6 +330,7 @@ pub struct TypeDefData { pub qualname: String, pub value: String, pub visibility: Visibility, + pub parent: Option, } /// Data for a reference to a type or trait. @@ -366,6 +370,7 @@ pub struct VariableData { pub qualname: String, pub span: Span, pub scope: NodeId, + pub parent: Option, pub value: String, pub type_value: String, pub visibility: Visibility, diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index e0475bfed931a..c4eba4171de04 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -365,6 +365,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { type_value: typ, value: String::new(), scope: 0, + parent: None, visibility: Visibility::Inherited, }.lower(self.tcx)); } @@ -488,6 +489,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { qualname: qualname, value: String::new(), visibility: Visibility::Inherited, + parent: None, }.lower(self.tcx)); } } @@ -531,13 +533,14 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { self.visit_expr(expr); } - fn process_const(&mut self, - id: ast::NodeId, - name: ast::Name, - span: Span, - typ: &ast::Ty, - expr: &ast::Expr, - vis: Visibility) { + fn process_assoc_const(&mut self, + id: ast::NodeId, + name: ast::Name, + span: Span, + typ: &ast::Ty, + expr: &ast::Expr, + parent_id: NodeId, + vis: Visibility) { let qualname = format!("::{}", self.tcx.node_path_str(id)); let sub_span = self.span.sub_span_after_keyword(span, keywords::Const); @@ -552,6 +555,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { value: self.span.snippet(expr.span), type_value: ty_to_string(&typ), scope: self.cur_scope, + parent: Some(parent_id), visibility: vis, }.lower(self.tcx)); } @@ -646,7 +650,8 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { qualname: qualname, type_value: enum_data.qualname.clone(), value: val, - scope: enum_data.scope + scope: enum_data.scope, + parent: Some(item.id), }.lower(self.tcx)); } } @@ -669,7 +674,8 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { qualname: qualname, type_value: enum_data.qualname.clone(), value: val, - scope: enum_data.scope + scope: enum_data.scope, + parent: Some(item.id), }.lower(self.tcx)); } } @@ -722,7 +728,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { } self.process_generic_params(type_parameters, item.span, "", item.id); for impl_item in impl_items { - self.visit_impl_item(impl_item); + self.process_impl_item(impl_item, item.id); } } @@ -792,7 +798,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { // walk generics and methods self.process_generic_params(generics, item.span, &qualname, item.id); for method in methods { - self.visit_trait_item(method) + self.process_trait_item(method, item.id) } } @@ -998,6 +1004,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { value: value, type_value: typ, scope: 0, + parent: None, visibility: Visibility::Inherited, }.lower(self.tcx)); } @@ -1046,6 +1053,57 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { } } } + + fn process_trait_item(&mut self, trait_item: &ast::TraitItem, trait_id: NodeId) { + self.process_macro_use(trait_item.span, trait_item.id); + match trait_item.node { + ast::TraitItemKind::Const(ref ty, Some(ref expr)) => { + self.process_assoc_const(trait_item.id, + trait_item.ident.name, + trait_item.span, + &ty, + &expr, + trait_id, + Visibility::Public); + } + ast::TraitItemKind::Method(ref sig, ref body) => { + self.process_method(sig, + body.as_ref().map(|x| &**x), + trait_item.id, + trait_item.ident.name, + Visibility::Public, + trait_item.span); + } + ast::TraitItemKind::Const(_, None) | + ast::TraitItemKind::Type(..) | + ast::TraitItemKind::Macro(_) => {} + } + } + + fn process_impl_item(&mut self, impl_item: &ast::ImplItem, impl_id: NodeId) { + self.process_macro_use(impl_item.span, impl_item.id); + match impl_item.node { + ast::ImplItemKind::Const(ref ty, ref expr) => { + self.process_assoc_const(impl_item.id, + impl_item.ident.name, + impl_item.span, + &ty, + &expr, + impl_id, + From::from(&impl_item.vis)); + } + ast::ImplItemKind::Method(ref sig, ref body) => { + self.process_method(sig, + Some(body), + impl_item.id, + impl_item.ident.name, + From::from(&impl_item.vis), + impl_item.span); + } + ast::ImplItemKind::Type(_) | + ast::ImplItemKind::Macro(_) => {} + } + } } impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor for DumpVisitor<'l, 'tcx, 'll, D> { @@ -1180,6 +1238,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor for DumpVisitor<'l, 'tcx, 'll, D> qualname: qualname.clone(), value: value, visibility: From::from(&item.vis), + parent: None, }.lower(self.tcx)); } @@ -1204,55 +1263,6 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor for DumpVisitor<'l, 'tcx, 'll, D> } } - fn visit_trait_item(&mut self, trait_item: &ast::TraitItem) { - self.process_macro_use(trait_item.span, trait_item.id); - match trait_item.node { - ast::TraitItemKind::Const(ref ty, Some(ref expr)) => { - self.process_const(trait_item.id, - trait_item.ident.name, - trait_item.span, - &ty, - &expr, - Visibility::Public); - } - ast::TraitItemKind::Method(ref sig, ref body) => { - self.process_method(sig, - body.as_ref().map(|x| &**x), - trait_item.id, - trait_item.ident.name, - Visibility::Public, - trait_item.span); - } - ast::TraitItemKind::Const(_, None) | - ast::TraitItemKind::Type(..) | - ast::TraitItemKind::Macro(_) => {} - } - } - - fn visit_impl_item(&mut self, impl_item: &ast::ImplItem) { - self.process_macro_use(impl_item.span, impl_item.id); - match impl_item.node { - ast::ImplItemKind::Const(ref ty, ref expr) => { - self.process_const(impl_item.id, - impl_item.ident.name, - impl_item.span, - &ty, - &expr, - From::from(&impl_item.vis)); - } - ast::ImplItemKind::Method(ref sig, ref body) => { - self.process_method(sig, - Some(body), - impl_item.id, - impl_item.ident.name, - From::from(&impl_item.vis), - impl_item.span); - } - ast::ImplItemKind::Type(_) | - ast::ImplItemKind::Macro(_) => {} - } - } - fn visit_ty(&mut self, t: &ast::Ty) { self.process_macro_use(t.span, t.id); match t.node { @@ -1416,6 +1426,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor for DumpVisitor<'l, 'tcx, 'll, D> value: value, type_value: String::new(), scope: 0, + parent: None, visibility: Visibility::Inherited, }.lower(self.tcx)); } diff --git a/src/librustc_save_analysis/external_data.rs b/src/librustc_save_analysis/external_data.rs index b7dded7b6247b..4333c6dd18e60 100644 --- a/src/librustc_save_analysis/external_data.rs +++ b/src/librustc_save_analysis/external_data.rs @@ -169,6 +169,7 @@ pub struct FunctionData { pub scope: DefId, pub value: String, pub visibility: Visibility, + pub parent: Option, } impl Lower for data::FunctionData { @@ -184,6 +185,7 @@ impl Lower for data::FunctionData { scope: make_def_id(self.scope, &tcx.map), value: self.value, visibility: self.visibility, + parent: self.parent.map(|id| make_def_id(id, &tcx.map)), } } } @@ -328,6 +330,7 @@ pub struct MethodData { pub value: String, pub decl_id: Option, pub visibility: Visibility, + pub parent: Option } impl Lower for data::MethodData { @@ -343,6 +346,7 @@ impl Lower for data::MethodData { value: self.value, decl_id: self.decl_id, visibility: self.visibility, + parent: Some(make_def_id(self.scope, &tcx.map)), } } } @@ -438,7 +442,8 @@ pub struct StructVariantData { pub qualname: String, pub type_value: String, pub value: String, - pub scope: DefId + pub scope: DefId, + pub parent: Option, } impl Lower for data::StructVariantData { @@ -453,6 +458,7 @@ impl Lower for data::StructVariantData { type_value: self.type_value, value: self.value, scope: make_def_id(self.scope, &tcx.map), + parent: self.parent.map(|id| make_def_id(id, &tcx.map)), } } } @@ -495,6 +501,7 @@ pub struct TupleVariantData { pub type_value: String, pub value: String, pub scope: DefId, + pub parent: Option, } impl Lower for data::TupleVariantData { @@ -509,6 +516,7 @@ impl Lower for data::TupleVariantData { type_value: self.type_value, value: self.value, scope: make_def_id(self.scope, &tcx.map), + parent: self.parent.map(|id| make_def_id(id, &tcx.map)), } } } @@ -522,6 +530,7 @@ pub struct TypeDefData { pub qualname: String, pub value: String, pub visibility: Visibility, + pub parent: Option, } impl Lower for data::TypeDefData { @@ -535,6 +544,7 @@ impl Lower for data::TypeDefData { qualname: self.qualname, value: self.value, visibility: self.visibility, + parent: self.parent.map(|id| make_def_id(id, &tcx.map)), } } } @@ -620,6 +630,7 @@ pub struct VariableData { pub scope: DefId, pub value: String, pub type_value: String, + pub parent: Option, pub visibility: Visibility, } @@ -636,6 +647,7 @@ impl Lower for data::VariableData { scope: make_def_id(self.scope, &tcx.map), value: self.value, type_value: self.type_value, + parent: self.parent.map(|id| make_def_id(id, &tcx.map)), visibility: self.visibility, } } diff --git a/src/librustc_save_analysis/json_api_dumper.rs b/src/librustc_save_analysis/json_api_dumper.rs index 9cc1badf7cdd9..874babb907e4c 100644 --- a/src/librustc_save_analysis/json_api_dumper.rs +++ b/src/librustc_save_analysis/json_api_dumper.rs @@ -17,6 +17,13 @@ use external_data::*; use data::{VariableKind, Visibility}; use dump::Dump; +// A dumper to dump a restricted set of JSON information, designed for use with +// libraries distributed without their source. Clients are likely to use type +// information here, and (for example) generate Rustdoc URLs, but don't need +// information for navigating the source of the crate. +// Relative to the regular JSON save-analysis info, this form is filtered to +// remove non-visible items, but includes some extra info for items (e.g., the +// parent field for finding the struct to which a field belongs). pub struct JsonApiDumper<'b, W: Write + 'b> { output: &'b mut W, result: Analysis, @@ -217,7 +224,7 @@ impl From for Option { name: data.name, qualname: data.qualname, value: data.value, - parent: None, + parent: data.parent.map(|id| From::from(id)), children: vec![], decl_id: None, }) @@ -232,7 +239,7 @@ impl From for Option { name: data.name, qualname: data.qualname, value: data.value, - parent: None, + parent: data.parent.map(|id| From::from(id)), children: vec![], decl_id: None, }) @@ -285,7 +292,7 @@ impl From for Option { qualname: data.qualname, value: data.value, children: vec![], - parent: None, + parent: data.parent.map(|id| From::from(id)), decl_id: None, }), _ => None, @@ -303,7 +310,7 @@ impl From for Option { qualname: data.qualname, value: data.value, children: vec![], - parent: None, + parent: data.parent.map(|id| From::from(id)), decl_id: data.decl_id.map(|id| From::from(id)), }), _ => None, @@ -354,7 +361,7 @@ impl From for Option { qualname: data.qualname, value: data.value, children: vec![], - parent: None, + parent: data.parent.map(|id| From::from(id)), decl_id: None, }), _ => None, @@ -377,7 +384,7 @@ impl From for Option { qualname: data.qualname, value: data.value, children: vec![], - parent: None, + parent: data.parent.map(|id| From::from(id)), decl_id: None, }), _ => None, diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 3645eb68394d9..9478e25cff7e0 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -141,6 +141,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { scope: self.enclosing_scope(item.id), value: make_signature(decl, generics), visibility: From::from(&item.vis), + parent: None, })) } ast::ItemKind::Static(ref typ, mt, ref expr) => { @@ -163,6 +164,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { qualname: qualname, span: sub_span.unwrap(), scope: self.enclosing_scope(item.id), + parent: None, value: value, type_value: ty_to_string(&typ), visibility: From::from(&item.vis), @@ -179,6 +181,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { qualname: qualname, span: sub_span.unwrap(), scope: self.enclosing_scope(item.id), + parent: None, value: self.span_utils.snippet(expr.span), type_value: ty_to_string(&typ), visibility: From::from(&item.vis), @@ -284,6 +287,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { qualname: qualname, span: sub_span.unwrap(), scope: scope, + parent: Some(scope), value: "".to_owned(), type_value: typ, visibility: From::from(&field.vis), @@ -366,6 +370,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { let sub_span = self.span_utils.sub_span_after_keyword(span, keywords::Fn); filter!(self.span_utils, sub_span, span, None); + let parent_scope = self.enclosing_scope(id); Some(FunctionData { id: id, name: name.to_string(), @@ -376,6 +381,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { // FIXME you get better data here by using the visitor. value: String::new(), visibility: vis, + parent: Some(parent_scope), }) } diff --git a/src/test/run-make/save-analysis/Makefile b/src/test/run-make/save-analysis/Makefile index 3c636baaedc5f..3711b6ea8959b 100644 --- a/src/test/run-make/save-analysis/Makefile +++ b/src/test/run-make/save-analysis/Makefile @@ -5,3 +5,4 @@ krate2: krate2.rs code: foo.rs krate2 $(RUSTC) foo.rs -Zsave-analysis-csv $(RUSTC) foo.rs -Zsave-analysis + $(RUSTC) foo.rs -Zsave-analysis-api From 377be7a5014052766784b2dda1d5b5e33e191b6b Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 30 Aug 2016 16:40:44 +1200 Subject: [PATCH 5/5] review comments --- src/librustc/session/config.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 8eb80472d6e09..5720978816249 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -848,7 +848,7 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, ls: bool = (false, parse_bool, [UNTRACKED], "list the symbols defined by a library crate"), save_analysis: bool = (false, parse_bool, [UNTRACKED], - "write syntax and type analysis (in JSON format) information, \ + "write syntax and type analysis (in JSON format) information, in \ addition to normal output"), save_analysis_csv: bool = (false, parse_bool, [UNTRACKED], "write syntax and type analysis (in CSV format) information, in addition to normal output"),