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