diff --git a/src/librustc_save_analysis/data.rs b/src/librustc_save_analysis/data.rs index 2275a1c5c65f2..15aaa77cc3518 100644 --- a/src/librustc_save_analysis/data.rs +++ b/src/librustc_save_analysis/data.rs @@ -102,6 +102,8 @@ pub struct EnumData { pub qualname: String, pub span: Span, pub scope: NodeId, + pub variants: Vec, + } /// Data for extern crates. @@ -212,6 +214,7 @@ pub struct MethodData { pub span: Span, pub scope: NodeId, pub value: String, + pub decl_id: Option, } /// Data for modules. @@ -223,6 +226,7 @@ pub struct ModData { pub span: Span, pub scope: NodeId, pub filename: String, + pub items: Vec, } /// Data for a reference to a module. @@ -242,7 +246,8 @@ pub struct StructData { pub ctor_id: NodeId, pub qualname: String, pub scope: NodeId, - pub value: String + pub value: String, + pub fields: Vec, } #[derive(Debug, RustcEncodable)] @@ -263,7 +268,8 @@ pub struct TraitData { pub name: String, pub qualname: String, pub scope: NodeId, - pub value: String + pub value: String, + pub items: Vec, } #[derive(Debug, RustcEncodable)] @@ -317,6 +323,7 @@ pub struct UseGlobData { #[derive(Debug, RustcEncodable)] pub struct VariableData { pub id: NodeId, + pub kind: VariableKind, pub name: String, pub qualname: String, pub span: Span, @@ -325,6 +332,14 @@ pub struct VariableData { pub type_value: String, } +#[derive(Debug, RustcEncodable)] +pub enum VariableKind { + Static, + Const, + Local, + Field, +} + /// Data for the use of some item (e.g., the use of a local variable, which /// will refer to that variables declaration (by ref_id)). #[derive(Debug, RustcEncodable)] diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 216d188a503e3..56c7436a8fe5c 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -30,7 +30,7 @@ use rustc::hir::def::Def; use rustc::hir::def_id::DefId; use rustc::session::Session; -use rustc::ty::{self, TyCtxt}; +use rustc::ty::{self, TyCtxt, ImplOrTraitItem, ImplOrTraitItemContainer}; use std::collections::HashSet; use std::hash::*; @@ -356,6 +356,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { if !self.span.filter_generated(sub_span, p.span) { self.dumper.variable(VariableData { id: id, + kind: VariableKind::Local, span: sub_span.expect("No span found for variable"), name: path_to_string(p), qualname: format!("{}::{}", qualname, path_to_string(p)), @@ -380,24 +381,42 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { let sig_str = ::make_signature(&sig.decl, &sig.generics); if body.is_some() { - if !self.span.filter_generated(Some(method_data.span), span) { - let mut data = method_data.clone(); - data.value = sig_str; - self.dumper.function(data.lower(self.tcx)); - } self.process_formals(&sig.decl.inputs, &method_data.qualname); - } else { - if !self.span.filter_generated(Some(method_data.span), span) { - self.dumper.method(MethodData { - id: method_data.id, - name: method_data.name, - span: method_data.span, - scope: method_data.scope, - qualname: method_data.qualname.clone(), - value: sig_str, - }.lower(self.tcx)); - } } + + // If the method is defined in an impl, then try and find the corresponding + // method decl in a trait, and if there is one, make a decl_id for it. This + // requires looking up the impl, then the trait, then searching for a method + // with the right name. + if !self.span.filter_generated(Some(method_data.span), span) { + let container = + self.tcx.impl_or_trait_item(self.tcx.map.local_def_id(id)).container(); + let decl_id = if let ImplOrTraitItemContainer::ImplContainer(id) = container { + self.tcx.trait_id_of_impl(id).and_then(|id| { + for item in &**self.tcx.trait_items(id) { + if let &ImplOrTraitItem::MethodTraitItem(ref m) = item { + if m.name == name { + return Some(m.def_id); + } + } + } + None + }) + } else { + None + }; + + self.dumper.method(MethodData { + id: method_data.id, + name: method_data.name, + span: method_data.span, + scope: method_data.scope, + qualname: method_data.qualname.clone(), + value: sig_str, + decl_id: decl_id, + }.lower(self.tcx)); + } + self.process_generic_params(&sig.generics, span, &method_data.qualname, id); } @@ -519,6 +538,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { if !self.span.filter_generated(sub_span, span) { self.dumper.variable(VariableData { span: sub_span.expect("No span found for variable"), + kind: VariableKind::Const, id: id, name: name.to_string(), qualname: qualname, @@ -542,17 +562,18 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { let qualname = format!("::{}", self.tcx.node_path_str(item.id)); let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Struct); - let val = if let ast::ItemKind::Struct(ast::VariantData::Struct(ref fields, _), _) = - item.node { + let (val, fields) = + if let ast::ItemKind::Struct(ast::VariantData::Struct(ref fields, _), _) = item.node + { let fields_str = fields.iter() .enumerate() .map(|(i, f)| f.ident.map(|i| i.to_string()) .unwrap_or(i.to_string())) .collect::>() .join(", "); - format!("{} {{ {} }}", name, fields_str) + (format!("{} {{ {} }}", name, fields_str), fields.iter().map(|f| f.id).collect()) } else { - String::new() + (String::new(), vec![]) }; if !self.span.filter_generated(sub_span, item.span) { @@ -563,7 +584,8 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { ctor_id: def.id(), qualname: qualname.clone(), scope: self.cur_scope, - value: val + value: val, + fields: fields, }.lower(self.tcx)); } @@ -718,7 +740,8 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { name: name, qualname: qualname.clone(), scope: self.cur_scope, - value: val + value: val, + items: methods.iter().map(|i| i.id).collect(), }.lower(self.tcx)); } @@ -958,6 +981,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { if !self.span.filter_generated(sub_span, p.span) { self.dumper.variable(VariableData { span: sub_span.expect("No span found for variable"), + kind: VariableKind::Local, id: id, name: path_to_string(p), qualname: format!("{}${}", path_to_string(p), id), @@ -1366,6 +1390,7 @@ impl<'v, 'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'v> for DumpVisitor<'l, 'tcx, if !self.span.filter_generated(Some(p.span), p.span) { self.dumper.variable(VariableData { span: p.span, + kind: VariableKind::Local, id: id, name: path_to_string(p), qualname: format!("{}${}", path_to_string(p), id), diff --git a/src/librustc_save_analysis/external_data.rs b/src/librustc_save_analysis/external_data.rs index dc51c41f296f2..7efd2624561e7 100644 --- a/src/librustc_save_analysis/external_data.rs +++ b/src/librustc_save_analysis/external_data.rs @@ -14,7 +14,7 @@ use rustc::ty::TyCtxt; use syntax::ast::{CrateNum, NodeId}; use syntax::codemap::{Span, CodeMap}; -use super::data; +use data; // FIXME: this should be pub(crate), but the current snapshot doesn't allow it yet pub trait Lower { @@ -90,6 +90,7 @@ pub struct EnumData { pub qualname: String, pub span: SpanData, pub scope: DefId, + pub variants: Vec } impl Lower for data::EnumData { @@ -103,6 +104,7 @@ impl Lower for data::EnumData { qualname: self.qualname, 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(), } } } @@ -319,6 +321,7 @@ pub struct MethodData { pub span: SpanData, pub scope: DefId, pub value: String, + pub decl_id: Option, } impl Lower for data::MethodData { @@ -332,6 +335,7 @@ impl Lower for data::MethodData { id: make_def_id(self.id, &tcx.map), qualname: self.qualname, value: self.value, + decl_id: self.decl_id, } } } @@ -345,6 +349,7 @@ pub struct ModData { pub span: SpanData, pub scope: DefId, pub filename: String, + pub items: Vec, } impl Lower for data::ModData { @@ -358,6 +363,7 @@ impl Lower for data::ModData { span: SpanData::from_span(self.span, tcx.sess.codemap()), 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(), } } } @@ -392,7 +398,8 @@ pub struct StructData { pub ctor_id: DefId, pub qualname: String, pub scope: DefId, - pub value: String + pub value: String, + pub fields: Vec, } impl Lower for data::StructData { @@ -406,7 +413,8 @@ impl Lower for data::StructData { ctor_id: make_def_id(self.ctor_id, &tcx.map), qualname: self.qualname, scope: make_def_id(self.scope, &tcx.map), - value: self.value + value: self.value, + fields: self.fields.into_iter().map(|id| make_def_id(id, &tcx.map)).collect(), } } } @@ -445,7 +453,8 @@ pub struct TraitData { pub id: DefId, pub qualname: String, pub scope: DefId, - pub value: String + pub value: String, + pub items: Vec, } impl Lower for data::TraitData { @@ -459,6 +468,7 @@ impl Lower for data::TraitData { qualname: self.qualname, 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(), } } } @@ -585,6 +595,7 @@ impl Lower for data::UseGlobData { pub struct VariableData { pub id: DefId, pub name: String, + pub kind: data::VariableKind, pub qualname: String, pub span: SpanData, pub scope: DefId, @@ -598,6 +609,7 @@ impl Lower for data::VariableData { fn lower(self, tcx: TyCtxt) -> VariableData { VariableData { id: make_def_id(self.id, &tcx.map), + kind: self.kind, name: self.name, qualname: self.qualname, span: SpanData::from_span(self.span, tcx.sess.codemap()), diff --git a/src/librustc_save_analysis/json_dumper.rs b/src/librustc_save_analysis/json_dumper.rs index 610a9ac2ad6ca..b1955cbd7b801 100644 --- a/src/librustc_save_analysis/json_dumper.rs +++ b/src/librustc_save_analysis/json_dumper.rs @@ -13,8 +13,9 @@ use std::io::Write; use rustc::hir::def_id::DefId; use rustc_serialize::json::as_json; -use super::external_data::*; -use super::dump::Dump; +use external_data::*; +use data::VariableKind; +use dump::Dump; pub struct JsonDumper<'b, W: Write + 'b> { output: &'b mut W, @@ -180,6 +181,8 @@ struct Def { name: String, qualname: String, value: String, + children: Vec, + decl_id: Option, } #[derive(Debug, RustcEncodable)] @@ -194,14 +197,19 @@ enum DefKind { 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 - Variable, + // value = type and init expression (for all variable kinds). + Local, + Static, + Const, + Field, } impl From for Def { @@ -213,6 +221,8 @@ impl From for Def { name: data.name, qualname: data.qualname, value: data.value, + children: data.variants.into_iter().map(|id| From::from(id)).collect(), + decl_id: None, } } } @@ -226,6 +236,8 @@ impl From for Def { name: data.name, qualname: data.qualname, value: data.value, + children: vec![], + decl_id: None, } } } @@ -238,6 +250,8 @@ impl From for Def { name: data.name, qualname: data.qualname, value: data.value, + children: vec![], + decl_id: None, } } } @@ -250,6 +264,8 @@ impl From for Def { name: data.name, qualname: data.qualname, value: data.value, + children: data.fields.into_iter().map(|id| From::from(id)).collect(), + decl_id: None, } } } @@ -262,6 +278,8 @@ impl From for Def { name: data.name, qualname: data.qualname, value: data.value, + children: data.items.into_iter().map(|id| From::from(id)).collect(), + decl_id: None, } } } @@ -274,18 +292,22 @@ impl From for Def { name: data.name, qualname: data.qualname, value: data.value, + children: vec![], + decl_id: None, } } } impl From for Def { fn from(data: MethodData) -> Def { Def { - kind: DefKind::Function, + kind: DefKind::Method, id: From::from(data.id), span: data.span, name: data.name, qualname: data.qualname, value: data.value, + children: vec![], + decl_id: data.decl_id.map(|id| From::from(id)), } } } @@ -298,6 +320,8 @@ impl From for Def { name: data.name, qualname: data.qualname, value: String::new(), + children: vec![], + decl_id: None, } } } @@ -310,6 +334,8 @@ impl From for Def { name: data.name, qualname: data.qualname, value: data.filename, + children: data.items.into_iter().map(|id| From::from(id)).collect(), + decl_id: None, } } } @@ -322,18 +348,27 @@ impl From for Def { name: data.name, qualname: data.qualname, value: data.value, + children: vec![], + decl_id: None, } } } impl From for Def { fn from(data: VariableData) -> Def { Def { - kind: DefKind::Variable, + kind: match data.kind { + VariableKind::Static => DefKind::Static, + VariableKind::Const => DefKind::Const, + VariableKind::Local => DefKind::Local, + VariableKind::Field => DefKind::Field, + }, id: From::from(data.id), span: data.span, name: data.name, qualname: data.qualname, value: data.value, + children: vec![], + decl_id: None, } } } diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 27f15756a9130..3335133816043 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -153,6 +153,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { filter!(self.span_utils, sub_span, item.span, None); Some(Data::VariableData(VariableData { id: item.id, + kind: VariableKind::Static, name: item.ident.to_string(), qualname: qualname, span: sub_span.unwrap(), @@ -167,6 +168,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { filter!(self.span_utils, sub_span, item.span, None); Some(Data::VariableData(VariableData { id: item.id, + kind: VariableKind::Const, name: item.ident.to_string(), qualname: qualname, span: sub_span.unwrap(), @@ -190,6 +192,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { span: sub_span.unwrap(), scope: self.enclosing_scope(item.id), filename: filename, + items: m.items.iter().map(|i| i.id).collect(), })) } ast::ItemKind::Enum(ref def, _) => { @@ -209,6 +212,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { span: sub_span.unwrap(), qualname: qualname, scope: self.enclosing_scope(item.id), + variants: def.variants.iter().map(|v| v.node.data.id()).collect(), })) } ast::ItemKind::Impl(_, _, _, ref trait_ref, ref typ, _) => { @@ -266,6 +270,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { filter!(self.span_utils, sub_span, field.span, None); Some(VariableData { id: field.id, + kind: VariableKind::Field, name: ident.to_string(), qualname: qualname, span: sub_span.unwrap(),