1
Fork 0

save-analysis: add parent info to api dumps

The parent id is used for constructing rustdoc URLs by clients
This commit is contained in:
Nick Cameron 2016-08-30 16:00:48 +12:00
parent 4e4306c6df
commit 4dc7b585a2
7 changed files with 113 additions and 70 deletions

View file

@ -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

View file

@ -166,6 +166,7 @@ pub struct FunctionData {
pub scope: NodeId,
pub value: String,
pub visibility: Visibility,
pub parent: Option<NodeId>,
}
/// 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<NodeId>,
}
#[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<NodeId>,
}
/// Data for a typedef.
@ -327,6 +330,7 @@ pub struct TypeDefData {
pub qualname: String,
pub value: String,
pub visibility: Visibility,
pub parent: Option<NodeId>,
}
/// 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<NodeId>,
pub value: String,
pub type_value: String,
pub visibility: Visibility,

View file

@ -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));
}

View file

@ -169,6 +169,7 @@ pub struct FunctionData {
pub scope: DefId,
pub value: String,
pub visibility: Visibility,
pub parent: Option<DefId>,
}
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<DefId>,
pub visibility: Visibility,
pub parent: Option<DefId>
}
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<DefId>,
}
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<DefId>,
}
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<DefId>,
}
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<DefId>,
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,
}
}

View file

@ -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<TupleVariantData> for Option<Def> {
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<StructVariantData> for Option<Def> {
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<FunctionData> for Option<Def> {
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<MethodData> for Option<Def> {
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<TypeDefData> for Option<Def> {
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<VariableData> for Option<Def> {
qualname: data.qualname,
value: data.value,
children: vec![],
parent: None,
parent: data.parent.map(|id| From::from(id)),
decl_id: None,
}),
_ => None,

View file

@ -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),
})
}

View file

@ -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