Auto merge of #36132 - nrc:save-std, r=@eddyb
Add --Zsave-analysis-api This is a save-analysis variation which can be used with libraries distributed without their source (e.g., libstd). It will allow IDEs and other tools to get info about types and create URLs to docs and source, without the unnecessary clutter of internal-only save-analysis info. I'm sure we'll iterate somewhat on the design, but this is a first draft.
This commit is contained in:
commit
e77d86c142
@ -849,9 +849,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, 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"),
|
||||
"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],
|
||||
@ -2365,6 +2369,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;
|
||||
|
@ -250,7 +250,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
|
||||
|
@ -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!();
|
||||
}
|
||||
|
@ -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<NodeId>,
|
||||
|
||||
pub visibility: Visibility,
|
||||
}
|
||||
|
||||
/// Data for extern crates.
|
||||
@ -135,6 +165,8 @@ pub struct FunctionData {
|
||||
pub span: Span,
|
||||
pub scope: NodeId,
|
||||
pub value: String,
|
||||
pub visibility: Visibility,
|
||||
pub parent: Option<NodeId>,
|
||||
}
|
||||
|
||||
/// Data about a function call.
|
||||
@ -215,6 +247,7 @@ pub struct MethodData {
|
||||
pub scope: NodeId,
|
||||
pub value: String,
|
||||
pub decl_id: Option<DefId>,
|
||||
pub visibility: Visibility,
|
||||
}
|
||||
|
||||
/// Data for modules.
|
||||
@ -227,6 +260,7 @@ pub struct ModData {
|
||||
pub scope: NodeId,
|
||||
pub filename: String,
|
||||
pub items: Vec<NodeId>,
|
||||
pub visibility: Visibility,
|
||||
}
|
||||
|
||||
/// Data for a reference to a module.
|
||||
@ -248,6 +282,7 @@ pub struct StructData {
|
||||
pub scope: NodeId,
|
||||
pub value: String,
|
||||
pub fields: Vec<NodeId>,
|
||||
pub visibility: Visibility,
|
||||
}
|
||||
|
||||
#[derive(Debug, RustcEncodable)]
|
||||
@ -258,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)]
|
||||
@ -270,6 +306,7 @@ pub struct TraitData {
|
||||
pub scope: NodeId,
|
||||
pub value: String,
|
||||
pub items: Vec<NodeId>,
|
||||
pub visibility: Visibility,
|
||||
}
|
||||
|
||||
#[derive(Debug, RustcEncodable)]
|
||||
@ -280,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.
|
||||
@ -291,6 +329,8 @@ pub struct TypeDefData {
|
||||
pub span: Span,
|
||||
pub qualname: String,
|
||||
pub value: String,
|
||||
pub visibility: Visibility,
|
||||
pub parent: Option<NodeId>,
|
||||
}
|
||||
|
||||
/// Data for a reference to a type or trait.
|
||||
@ -308,7 +348,8 @@ pub struct UseData {
|
||||
pub span: Span,
|
||||
pub name: String,
|
||||
pub mod_id: Option<DefId>,
|
||||
pub scope: NodeId
|
||||
pub scope: NodeId,
|
||||
pub visibility: Visibility,
|
||||
}
|
||||
|
||||
#[derive(Debug, RustcEncodable)]
|
||||
@ -316,7 +357,8 @@ pub struct UseGlobData {
|
||||
pub id: NodeId,
|
||||
pub span: Span,
|
||||
pub names: Vec<String>,
|
||||
pub scope: NodeId
|
||||
pub scope: NodeId,
|
||||
pub visibility: Visibility,
|
||||
}
|
||||
|
||||
/// Data for local and global variables (consts and statics).
|
||||
@ -328,8 +370,10 @@ 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,
|
||||
}
|
||||
|
||||
#[derive(Debug, RustcEncodable)]
|
||||
|
@ -365,7 +365,9 @@ 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,
|
||||
parent: None,
|
||||
visibility: Visibility::Inherited,
|
||||
}.lower(self.tcx));
|
||||
}
|
||||
}
|
||||
@ -377,6 +379,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);
|
||||
|
||||
@ -417,6 +420,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));
|
||||
}
|
||||
|
||||
@ -484,7 +488,9 @@ 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,
|
||||
parent: None,
|
||||
}.lower(self.tcx));
|
||||
}
|
||||
}
|
||||
@ -528,12 +534,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) {
|
||||
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);
|
||||
@ -547,7 +555,9 @@ 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,
|
||||
parent: Some(parent_id),
|
||||
visibility: vis,
|
||||
}.lower(self.tcx));
|
||||
}
|
||||
|
||||
@ -589,6 +599,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));
|
||||
}
|
||||
|
||||
@ -640,7 +651,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));
|
||||
}
|
||||
}
|
||||
@ -663,7 +675,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));
|
||||
}
|
||||
}
|
||||
@ -716,7 +729,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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -745,6 +758,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));
|
||||
}
|
||||
|
||||
@ -785,7 +799,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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -990,7 +1004,9 @@ 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,
|
||||
parent: None,
|
||||
visibility: Visibility::Inherited,
|
||||
}.lower(self.tcx));
|
||||
}
|
||||
}
|
||||
@ -1038,6 +1054,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> {
|
||||
@ -1073,7 +1140,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);
|
||||
@ -1096,7 +1164,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);
|
||||
@ -1168,7 +1237,9 @@ 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),
|
||||
parent: None,
|
||||
}.lower(self.tcx));
|
||||
}
|
||||
|
||||
@ -1193,51 +1264,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);
|
||||
}
|
||||
ast::TraitItemKind::Method(ref sig, ref body) => {
|
||||
self.process_method(sig,
|
||||
body.as_ref().map(|x| &**x),
|
||||
trait_item.id,
|
||||
trait_item.ident.name,
|
||||
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);
|
||||
}
|
||||
ast::ImplItemKind::Method(ref sig, ref body) => {
|
||||
self.process_method(sig,
|
||||
Some(body),
|
||||
impl_item.id,
|
||||
impl_item.ident.name,
|
||||
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 {
|
||||
@ -1400,7 +1426,9 @@ 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,
|
||||
parent: None,
|
||||
visibility: Visibility::Inherited,
|
||||
}.lower(self.tcx));
|
||||
}
|
||||
}
|
||||
|
@ -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<DefId>
|
||||
pub variants: Vec<DefId>,
|
||||
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,8 @@ pub struct FunctionData {
|
||||
pub span: SpanData,
|
||||
pub scope: DefId,
|
||||
pub value: String,
|
||||
pub visibility: Visibility,
|
||||
pub parent: Option<DefId>,
|
||||
}
|
||||
|
||||
impl Lower for data::FunctionData {
|
||||
@ -180,6 +184,8 @@ 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,
|
||||
parent: self.parent.map(|id| make_def_id(id, &tcx.map)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -323,6 +329,8 @@ pub struct MethodData {
|
||||
pub scope: DefId,
|
||||
pub value: String,
|
||||
pub decl_id: Option<DefId>,
|
||||
pub visibility: Visibility,
|
||||
pub parent: Option<DefId>
|
||||
}
|
||||
|
||||
impl Lower for data::MethodData {
|
||||
@ -337,6 +345,8 @@ impl Lower for data::MethodData {
|
||||
qualname: self.qualname,
|
||||
value: self.value,
|
||||
decl_id: self.decl_id,
|
||||
visibility: self.visibility,
|
||||
parent: Some(make_def_id(self.scope, &tcx.map)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -351,6 +361,7 @@ pub struct ModData {
|
||||
pub scope: DefId,
|
||||
pub filename: String,
|
||||
pub items: Vec<DefId>,
|
||||
pub visibility: Visibility,
|
||||
}
|
||||
|
||||
impl Lower for data::ModData {
|
||||
@ -365,6 +376,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 +413,7 @@ pub struct StructData {
|
||||
pub scope: DefId,
|
||||
pub value: String,
|
||||
pub fields: Vec<DefId>,
|
||||
pub visibility: Visibility,
|
||||
}
|
||||
|
||||
impl Lower for data::StructData {
|
||||
@ -416,6 +429,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,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -428,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 {
|
||||
@ -443,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)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -456,6 +472,7 @@ pub struct TraitData {
|
||||
pub scope: DefId,
|
||||
pub value: String,
|
||||
pub items: Vec<DefId>,
|
||||
pub visibility: Visibility,
|
||||
}
|
||||
|
||||
impl Lower for data::TraitData {
|
||||
@ -470,6 +487,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,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -483,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 {
|
||||
@ -497,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)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -509,6 +529,8 @@ pub struct TypeDefData {
|
||||
pub span: SpanData,
|
||||
pub qualname: String,
|
||||
pub value: String,
|
||||
pub visibility: Visibility,
|
||||
pub parent: Option<DefId>,
|
||||
}
|
||||
|
||||
impl Lower for data::TypeDefData {
|
||||
@ -521,6 +543,8 @@ impl Lower for data::TypeDefData {
|
||||
span: SpanData::from_span(self.span, tcx.sess.codemap()),
|
||||
qualname: self.qualname,
|
||||
value: self.value,
|
||||
visibility: self.visibility,
|
||||
parent: self.parent.map(|id| make_def_id(id, &tcx.map)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -553,7 +577,8 @@ pub struct UseData {
|
||||
pub span: SpanData,
|
||||
pub name: String,
|
||||
pub mod_id: Option<DefId>,
|
||||
pub scope: DefId
|
||||
pub scope: DefId,
|
||||
pub visibility: Visibility,
|
||||
}
|
||||
|
||||
impl Lower for data::UseData {
|
||||
@ -566,6 +591,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 +601,8 @@ pub struct UseGlobData {
|
||||
pub id: DefId,
|
||||
pub span: SpanData,
|
||||
pub names: Vec<String>,
|
||||
pub scope: DefId
|
||||
pub scope: DefId,
|
||||
pub visibility: Visibility,
|
||||
}
|
||||
|
||||
impl Lower for data::UseGlobData {
|
||||
@ -587,6 +614,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 +630,8 @@ pub struct VariableData {
|
||||
pub scope: DefId,
|
||||
pub value: String,
|
||||
pub type_value: String,
|
||||
pub parent: Option<DefId>,
|
||||
pub visibility: Visibility,
|
||||
}
|
||||
|
||||
impl Lower for data::VariableData {
|
||||
@ -617,6 +647,8 @@ 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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
393
src/librustc_save_analysis/json_api_dumper.rs
Normal file
393
src/librustc_save_analysis/json_api_dumper.rs
Normal file
@ -0,0 +1,393 @@
|
||||
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use std::io::Write;
|
||||
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc_serialize::json::as_json;
|
||||
|
||||
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,
|
||||
}
|
||||
|
||||
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<CratePreludeData>,
|
||||
imports: Vec<Import>,
|
||||
defs: Vec<Def>,
|
||||
}
|
||||
|
||||
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<DefId> 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<UseData> for Option<Import> {
|
||||
fn from(data: UseData) -> Option<Import> {
|
||||
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<UseGlobData> for Option<Import> {
|
||||
fn from(data: UseGlobData) -> Option<Import> {
|
||||
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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, RustcEncodable)]
|
||||
struct Def {
|
||||
kind: DefKind,
|
||||
id: Id,
|
||||
span: SpanData,
|
||||
name: String,
|
||||
qualname: String,
|
||||
value: String,
|
||||
parent: Option<Id>,
|
||||
children: Vec<Id>,
|
||||
decl_id: Option<Id>,
|
||||
}
|
||||
|
||||
#[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<EnumData> for Option<Def> {
|
||||
fn from(data: EnumData) -> Option<Def> {
|
||||
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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TupleVariantData> for Option<Def> {
|
||||
fn from(data: TupleVariantData) -> Option<Def> {
|
||||
Some(Def {
|
||||
kind: DefKind::Tuple,
|
||||
id: From::from(data.id),
|
||||
span: data.span,
|
||||
name: data.name,
|
||||
qualname: data.qualname,
|
||||
value: data.value,
|
||||
parent: data.parent.map(|id| From::from(id)),
|
||||
children: vec![],
|
||||
decl_id: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
impl From<StructVariantData> for Option<Def> {
|
||||
fn from(data: StructVariantData) -> Option<Def> {
|
||||
Some(Def {
|
||||
kind: DefKind::Struct,
|
||||
id: From::from(data.id),
|
||||
span: data.span,
|
||||
name: data.name,
|
||||
qualname: data.qualname,
|
||||
value: data.value,
|
||||
parent: data.parent.map(|id| From::from(id)),
|
||||
children: vec![],
|
||||
decl_id: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
impl From<StructData> for Option<Def> {
|
||||
fn from(data: StructData) -> Option<Def> {
|
||||
match data.visibility {
|
||||
Visibility::Public => 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,
|
||||
}),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl From<TraitData> for Option<Def> {
|
||||
fn from(data: TraitData) -> Option<Def> {
|
||||
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<FunctionData> for Option<Def> {
|
||||
fn from(data: FunctionData) -> Option<Def> {
|
||||
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: data.parent.map(|id| From::from(id)),
|
||||
decl_id: None,
|
||||
}),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl From<MethodData> for Option<Def> {
|
||||
fn from(data: MethodData) -> Option<Def> {
|
||||
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: data.parent.map(|id| From::from(id)),
|
||||
decl_id: data.decl_id.map(|id| From::from(id)),
|
||||
}),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl From<MacroData> for Option<Def> {
|
||||
fn from(data: MacroData) -> Option<Def> {
|
||||
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<ModData> for Option<Def> {
|
||||
fn from(data:ModData) -> Option<Def> {
|
||||
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<TypeDefData> for Option<Def> {
|
||||
fn from(data: TypeDefData) -> Option<Def> {
|
||||
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: data.parent.map(|id| From::from(id)),
|
||||
decl_id: None,
|
||||
}),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl From<VariableData> for Option<Def> {
|
||||
fn from(data: VariableData) -> Option<Def> {
|
||||
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: data.parent.map(|id| From::from(id)),
|
||||
decl_id: None,
|
||||
}),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
@ -138,6 +140,8 @@ 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),
|
||||
parent: None,
|
||||
}))
|
||||
}
|
||||
ast::ItemKind::Static(ref typ, mt, ref expr) => {
|
||||
@ -160,8 +164,10 @@ 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),
|
||||
}))
|
||||
}
|
||||
ast::ItemKind::Const(ref typ, ref expr) => {
|
||||
@ -175,8 +181,10 @@ 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),
|
||||
}))
|
||||
}
|
||||
ast::ItemKind::Mod(ref m) => {
|
||||
@ -195,6 +203,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, _) => {
|
||||
@ -215,6 +224,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, _) => {
|
||||
@ -277,8 +287,10 @@ 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),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
@ -291,7 +303,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
||||
name: ast::Name, span: Span) -> Option<FunctionData> {
|
||||
// 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 {
|
||||
@ -304,7 +316,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,
|
||||
@ -325,8 +337,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,
|
||||
@ -358,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(),
|
||||
@ -367,6 +380,8 @@ 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,
|
||||
parent: Some(parent_scope),
|
||||
})
|
||||
}
|
||||
|
||||
@ -728,13 +743,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",
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -804,6 +820,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 => dump!(JsonApiDumper::new(output)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user