From a0a987722e8a38494d818443819ad0853771b37e Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 11 May 2016 09:59:35 -0700 Subject: [PATCH 1/3] save-analysis: attempt number 2 at a JSON version --- src/librustc_save_analysis/csv_dumper.rs | 2 +- src/librustc_save_analysis/data.rs | 12 +- src/librustc_save_analysis/dump.rs | 2 +- src/librustc_save_analysis/dump_visitor.rs | 26 +- src/librustc_save_analysis/external_data.rs | 28 +- src/librustc_save_analysis/json_dumper.rs | 411 ++++++++++++++++++-- src/librustc_save_analysis/lib.rs | 3 + 7 files changed, 423 insertions(+), 61 deletions(-) diff --git a/src/librustc_save_analysis/csv_dumper.rs b/src/librustc_save_analysis/csv_dumper.rs index ac658af4006..e7cc534c5b5 100644 --- a/src/librustc_save_analysis/csv_dumper.rs +++ b/src/librustc_save_analysis/csv_dumper.rs @@ -331,7 +331,7 @@ impl<'b, W: Write + 'b> Dump for CsvDumper<'b, W> { self.record("type_ref", data.span, values); } - fn typedef(&mut self, data: TypedefData) { + fn typedef(&mut self, data: TypeDefData) { let id = data.id.index.as_u32().to_string(); let values = make_values_str(&[ ("id", &id), diff --git a/src/librustc_save_analysis/data.rs b/src/librustc_save_analysis/data.rs index 19f9ba95b35..2275a1c5c65 100644 --- a/src/librustc_save_analysis/data.rs +++ b/src/librustc_save_analysis/data.rs @@ -62,7 +62,7 @@ pub enum Data { /// Data for a tuple variant. TupleVariantData(TupleVariantData), /// Data for a typedef. - TypeDefData(TypedefData), + TypeDefData(TypeDefData), /// Data for a reference to a type or trait. TypeRefData(TypeRefData), /// Data for a use statement. @@ -97,6 +97,7 @@ pub struct ExternalCrateData { #[derive(Clone, Debug, RustcEncodable)] pub struct EnumData { pub id: NodeId, + pub name: String, pub value: String, pub qualname: String, pub span: Span, @@ -131,6 +132,7 @@ pub struct FunctionData { pub declaration: Option, pub span: Span, pub scope: NodeId, + pub value: String, } /// Data about a function call. @@ -205,9 +207,11 @@ pub struct MethodCallData { #[derive(Clone, Debug, RustcEncodable)] pub struct MethodData { pub id: NodeId, + pub name: String, pub qualname: String, pub span: Span, pub scope: NodeId, + pub value: String, } /// Data for modules. @@ -233,6 +237,7 @@ pub struct ModRefData { #[derive(Debug, RustcEncodable)] pub struct StructData { pub span: Span, + pub name: String, pub id: NodeId, pub ctor_id: NodeId, pub qualname: String, @@ -243,6 +248,7 @@ pub struct StructData { #[derive(Debug, RustcEncodable)] pub struct StructVariantData { pub span: Span, + pub name: String, pub id: NodeId, pub qualname: String, pub type_value: String, @@ -254,6 +260,7 @@ pub struct StructVariantData { pub struct TraitData { pub span: Span, pub id: NodeId, + pub name: String, pub qualname: String, pub scope: NodeId, pub value: String @@ -272,8 +279,9 @@ pub struct TupleVariantData { /// Data for a typedef. #[derive(Debug, RustcEncodable)] -pub struct TypedefData { +pub struct TypeDefData { pub id: NodeId, + pub name: String, pub span: Span, pub qualname: String, pub value: String, diff --git a/src/librustc_save_analysis/dump.rs b/src/librustc_save_analysis/dump.rs index adbf1e0a35e..18241b394cc 100644 --- a/src/librustc_save_analysis/dump.rs +++ b/src/librustc_save_analysis/dump.rs @@ -30,7 +30,7 @@ pub trait Dump { fn trait_data(&mut self, TraitData) {} fn tuple_variant(&mut self, TupleVariantData) {} fn type_ref(&mut self, TypeRefData) {} - fn typedef(&mut self, TypedefData) {} + fn typedef(&mut self, TypeDefData) {} fn use_data(&mut self, UseData) {} fn use_glob(&mut self, UseGlobData) {} fn variable(&mut self, VariableData) {} diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index f0dd7b8b9bb..6f84ccc9e36 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -397,9 +397,11 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { 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: String::new(), // TODO }.lower(self.tcx)); } } @@ -455,16 +457,18 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { let param_sub_spans = self.span.spans_for_ty_params(full_span, (generics.ty_params.len() as isize)); for (param, param_ss) in generics.ty_params.iter().zip(param_sub_spans) { + let name = escape(self.span.snippet(param_ss)); // Append $id to name to make sure each one is unique - let name = format!("{}::{}${}", - prefix, - escape(self.span.snippet(param_ss)), - id); + let qualname = format!("{}::{}${}", + prefix, + name, + id); if !self.span.filter_generated(Some(param_ss), full_span) { - self.dumper.typedef(TypedefData { + self.dumper.typedef(TypeDefData { span: param_ss, + name: name, id: param.id, - qualname: name, + qualname: qualname, value: String::new() }.lower(self.tcx)); } @@ -548,6 +552,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { self.dumper.struct_data(StructData { span: sub_span.expect("No span found for struct"), id: item.id, + name: item.ident.to_string(), ctor_id: def.id(), qualname: qualname.clone(), scope: self.cur_scope, @@ -580,10 +585,10 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { } for variant in &enum_definition.variants { - let name = &variant.node.name.name.as_str(); + let name = variant.node.name.name.to_string(); let mut qualname = enum_data.qualname.clone(); qualname.push_str("::"); - qualname.push_str(name); + qualname.push_str(&name); let val = self.span.snippet(variant.span); match variant.node.data { @@ -593,6 +598,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { self.dumper.struct_variant(StructVariantData { span: sub_span.expect("No span found for struct variant"), id: variant.node.data.id(), + name: name, qualname: qualname, type_value: enum_data.qualname.clone(), value: val, @@ -679,6 +685,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { self.dumper.trait_data(TraitData { span: sub_span.expect("No span found for trait"), id: item.id, + name: item.ident.to_string(), qualname: qualname.clone(), scope: self.cur_scope, value: val @@ -1107,8 +1114,9 @@ impl<'v, 'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'v> for DumpVisitor<'l, 'tcx, let value = ty_to_string(&ty); let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Type); if !self.span.filter_generated(sub_span, item.span) { - self.dumper.typedef(TypedefData { + self.dumper.typedef(TypeDefData { span: sub_span.expect("No span found for typedef"), + name: item.ident.to_string(), id: item.id, qualname: qualname.clone(), value: value diff --git a/src/librustc_save_analysis/external_data.rs b/src/librustc_save_analysis/external_data.rs index 51134f8383b..dc51c41f296 100644 --- a/src/librustc_save_analysis/external_data.rs +++ b/src/librustc_save_analysis/external_data.rs @@ -86,6 +86,7 @@ impl Lower for data::CratePreludeData { pub struct EnumData { pub id: DefId, pub value: String, + pub name: String, pub qualname: String, pub span: SpanData, pub scope: DefId, @@ -97,6 +98,7 @@ impl Lower for data::EnumData { fn lower(self, tcx: TyCtxt) -> EnumData { EnumData { id: make_def_id(self.id, &tcx.map), + name: self.name, value: self.value, qualname: self.qualname, span: SpanData::from_span(self.span, tcx.sess.codemap()), @@ -160,6 +162,7 @@ pub struct FunctionData { pub declaration: Option, pub span: SpanData, pub scope: DefId, + pub value: String, } impl Lower for data::FunctionData { @@ -173,6 +176,7 @@ impl Lower for data::FunctionData { declaration: self.declaration, span: SpanData::from_span(self.span, tcx.sess.codemap()), scope: make_def_id(self.scope, &tcx.map), + value: self.value, } } } @@ -268,7 +272,6 @@ pub struct MacroUseData { // we use the callee span to reference the associated macro definition. pub callee_span: SpanData, pub scope: DefId, - pub imported: bool, } impl Lower for data::MacroUseData { @@ -281,7 +284,6 @@ impl Lower for data::MacroUseData { qualname: self.qualname, callee_span: SpanData::from_span(self.callee_span, tcx.sess.codemap()), scope: make_def_id(self.scope, &tcx.map), - imported: self.imported, } } } @@ -312,9 +314,11 @@ impl Lower for data::MethodCallData { #[derive(Clone, Debug, RustcEncodable)] pub struct MethodData { pub id: DefId, + pub name: String, pub qualname: String, pub span: SpanData, pub scope: DefId, + pub value: String, } impl Lower for data::MethodData { @@ -323,9 +327,11 @@ impl Lower for data::MethodData { fn lower(self, tcx: TyCtxt) -> MethodData { MethodData { span: SpanData::from_span(self.span, tcx.sess.codemap()), + name: self.name, scope: make_def_id(self.scope, &tcx.map), id: make_def_id(self.id, &tcx.map), qualname: self.qualname, + value: self.value, } } } @@ -381,6 +387,7 @@ impl Lower for data::ModRefData { #[derive(Debug, RustcEncodable)] pub struct StructData { pub span: SpanData, + pub name: String, pub id: DefId, pub ctor_id: DefId, pub qualname: String, @@ -394,6 +401,7 @@ impl Lower for data::StructData { fn lower(self, tcx: TyCtxt) -> StructData { StructData { span: SpanData::from_span(self.span, tcx.sess.codemap()), + name: self.name, id: make_def_id(self.id, &tcx.map), ctor_id: make_def_id(self.ctor_id, &tcx.map), qualname: self.qualname, @@ -406,6 +414,7 @@ impl Lower for data::StructData { #[derive(Debug, RustcEncodable)] pub struct StructVariantData { pub span: SpanData, + pub name: String, pub id: DefId, pub qualname: String, pub type_value: String, @@ -419,6 +428,7 @@ impl Lower for data::StructVariantData { fn lower(self, tcx: TyCtxt) -> StructVariantData { StructVariantData { span: SpanData::from_span(self.span, tcx.sess.codemap()), + name: self.name, id: make_def_id(self.id, &tcx.map), qualname: self.qualname, type_value: self.type_value, @@ -431,6 +441,7 @@ impl Lower for data::StructVariantData { #[derive(Debug, RustcEncodable)] pub struct TraitData { pub span: SpanData, + pub name: String, pub id: DefId, pub qualname: String, pub scope: DefId, @@ -443,6 +454,7 @@ impl Lower for data::TraitData { fn lower(self, tcx: TyCtxt) -> TraitData { TraitData { span: SpanData::from_span(self.span, tcx.sess.codemap()), + name: self.name, id: make_def_id(self.id, &tcx.map), qualname: self.qualname, scope: make_def_id(self.scope, &tcx.map), @@ -480,19 +492,21 @@ impl Lower for data::TupleVariantData { /// Data for a typedef. #[derive(Debug, RustcEncodable)] -pub struct TypedefData { +pub struct TypeDefData { pub id: DefId, + pub name: String, pub span: SpanData, pub qualname: String, pub value: String, } -impl Lower for data::TypedefData { - type Target = TypedefData; +impl Lower for data::TypeDefData { + type Target = TypeDefData; - fn lower(self, tcx: TyCtxt) -> TypedefData { - TypedefData { + fn lower(self, tcx: TyCtxt) -> TypeDefData { + TypeDefData { id: make_def_id(self.id, &tcx.map), + name: self.name, span: SpanData::from_span(self.span, tcx.sess.codemap()), qualname: self.qualname, value: self.value, diff --git a/src/librustc_save_analysis/json_dumper.rs b/src/librustc_save_analysis/json_dumper.rs index 9ad2bcef4ed..156a6f5cc97 100644 --- a/src/librustc_save_analysis/json_dumper.rs +++ b/src/librustc_save_analysis/json_dumper.rs @@ -10,6 +10,7 @@ use std::io::Write; +use rustc::hir::def_id::DefId; use rustc_serialize::json::as_json; use super::external_data::*; @@ -17,66 +18,394 @@ use super::dump::Dump; pub struct JsonDumper<'b, W: Write + 'b> { output: &'b mut W, - first: bool, + result: Analysis, } impl<'b, W: Write> JsonDumper<'b, W> { pub fn new(writer: &'b mut W) -> JsonDumper<'b, W> { - if let Err(_) = write!(writer, "[") { - error!("Error writing output"); - } - JsonDumper { output: writer, first: true } + JsonDumper { output: writer, result: Analysis::new() } } } impl<'b, W: Write> Drop for JsonDumper<'b, W> { fn drop(&mut self) { - if let Err(_) = write!(self.output, "]") { + if let Err(_) = write!(self.output, "{}", as_json(&self.result)) { error!("Error writing output"); } } } macro_rules! impl_fn { - ($fn_name: ident, $data_type: ident) => { + ($fn_name: ident, $data_type: ident, $bin: ident) => { fn $fn_name(&mut self, data: $data_type) { - if self.first { - self.first = false; - } else { - if let Err(_) = write!(self.output, ",") { - error!("Error writing output"); - } - } - if let Err(_) = write!(self.output, "{}", as_json(&data)) { - error!("Error writing output '{}'", as_json(&data)); - } + self.result.$bin.push(From::from(data)); } } } impl<'b, W: Write + 'b> Dump for JsonDumper<'b, W> { - impl_fn!(crate_prelude, CratePreludeData); - impl_fn!(enum_data, EnumData); - impl_fn!(extern_crate, ExternCrateData); - impl_fn!(impl_data, ImplData); - impl_fn!(inheritance, InheritanceData); - impl_fn!(function, FunctionData); - impl_fn!(function_ref, FunctionRefData); - impl_fn!(function_call, FunctionCallData); - impl_fn!(method, MethodData); - impl_fn!(method_call, MethodCallData); - impl_fn!(macro_data, MacroData); - impl_fn!(macro_use, MacroUseData); - impl_fn!(mod_data, ModData); - impl_fn!(mod_ref, ModRefData); - impl_fn!(struct_data, StructData); - impl_fn!(struct_variant, StructVariantData); - impl_fn!(trait_data, TraitData); - impl_fn!(tuple_variant, TupleVariantData); - impl_fn!(type_ref, TypeRefData); - impl_fn!(typedef, TypedefData); - impl_fn!(use_data, UseData); - impl_fn!(use_glob, UseGlobData); - impl_fn!(variable, VariableData); - impl_fn!(variable_ref, VariableRefData); + fn crate_prelude(&mut self, data: CratePreludeData) { + self.result.prelude = Some(data) + } + + impl_fn!(extern_crate, ExternCrateData, imports); + 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); + + impl_fn!(function_ref, FunctionRefData, refs); + impl_fn!(function_call, FunctionCallData, refs); + impl_fn!(method_call, MethodCallData, refs); + impl_fn!(mod_ref, ModRefData, refs); + impl_fn!(type_ref, TypeRefData, refs); + impl_fn!(variable_ref, VariableRefData, refs); + + impl_fn!(macro_use, MacroUseData, macro_refs); + + // FIXME store this instead of throwing it away. + fn impl_data(&mut self, _data: ImplData) {} + fn inheritance(&mut self, _data: InheritanceData) {} +} + +// FIXME do we want to change ExternalData to this mode? It will break DXR. +// 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, + refs: Vec, + macro_refs: Vec, +} + +impl Analysis { + fn new() -> Analysis { + Analysis { + prelude: None, + imports: vec![], + defs: vec![], + refs: vec![], + macro_refs: vec![], + } + } +} + +#[derive(Debug, RustcEncodable)] +struct Import { + kind: ImportKind, + id: DefId, + span: SpanData, + name: String, + value: String, +} + +#[derive(Debug, RustcEncodable)] +enum ImportKind { + ExternCrate, + Use, + GlobUse, +} + +impl From for Import { + fn from(data: ExternCrateData) -> Import { + Import { + kind: ImportKind::ExternCrate, + id: data.id, + span: data.span, + name: data.name, + value: String::new(), + } + } +} +impl From for Import { + fn from(data: UseData) -> Import { + Import { + kind: ImportKind::Use, + id: data.id, + span: data.span, + name: data.name, + value: String::new(), + } + } +} +impl From for Import { + fn from(data: UseGlobData) -> Import { + Import { + kind: ImportKind::GlobUse, + id: data.id, + span: data.span, + name: "*".to_owned(), + value: data.names.join(", "), + } + } +} + +#[derive(Debug, RustcEncodable)] +struct Def { + kind: DefKind, + id: DefId, + span: SpanData, + name: String, + qualname: String, + value: String, +} + +#[derive(Debug, RustcEncodable)] +enum DefKind { + // value = type + generics + Enum, + // value = type + generics + Tuple, + // value = type + generics + types + Struct, + // value = type + generics + Trait, + // value = type + generics + Function, + // No id + Macro, + // value = file_name + Mod, + // value = aliased type + Type, + // value = type and init expression + Variable, +} +// TODO value for function and method +// TODO none of the values are right. + +impl From for Def { + fn from(data: EnumData) -> Def { + Def { + kind: DefKind::Enum, + id: data.id, + span: data.span, + name: data.name, + qualname: data.qualname, + value: data.value, + } + } +} + +impl From for Def { + fn from(data: TupleVariantData) -> Def { + Def { + kind: DefKind::Tuple, + id: data.id, + span: data.span, + name: data.name, + qualname: data.qualname, + value: data.value, + } + } +} +impl From for Def { + fn from(data: StructVariantData) -> Def { + Def { + kind: DefKind::Struct, + id: data.id, + span: data.span, + name: data.name, + qualname: data.qualname, + value: data.value, + } + } +} +impl From for Def { + fn from(data: StructData) -> Def { + Def { + kind: DefKind::Struct, + id: data.id, + span: data.span, + name: data.name, + qualname: data.qualname, + value: data.value, + } + } +} +impl From for Def { + fn from(data: TraitData) -> Def { + Def { + kind: DefKind::Trait, + id: data.id, + span: data.span, + name: data.name, + qualname: data.qualname, + value: data.value, + } + } +} +impl From for Def { + fn from(data: FunctionData) -> Def { + Def { + kind: DefKind::Function, + id: data.id, + span: data.span, + name: data.name, + qualname: data.qualname, + value: data.value, + } + } +} +impl From for Def { + fn from(data: MethodData) -> Def { + Def { + kind: DefKind::Function, + id: data.id, + span: data.span, + name: data.name, + qualname: data.qualname, + value: data.value, + } + } +} +impl From for Def { + fn from(data: MacroData) -> Def { + Def { + kind: DefKind::Macro, + id: null_def_id(), + span: data.span, + name: data.name, + qualname: data.qualname, + value: String::new(), + } + } +} +impl From for Def { + fn from(data:ModData) -> Def { + Def { + kind: DefKind::Mod, + id: data.id, + span: data.span, + name: data.name, + qualname: data.qualname, + value: data.filename, + } + } +} +impl From for Def { + fn from(data: TypeDefData) -> Def { + Def { + kind: DefKind::Type, + id: data.id, + span: data.span, + name: data.name, + qualname: data.qualname, + value: data.value, + } + } +} +impl From for Def { + fn from(data: VariableData) -> Def { + Def { + kind: DefKind::Variable, + id: data.id, + span: data.span, + name: data.name, + qualname: data.qualname, + value: data.value, + } + } +} + +#[derive(Debug, RustcEncodable)] +enum RefKind { + Function, + Mod, + Type, + Variable, +} + +#[derive(Debug, RustcEncodable)] +struct Ref { + kind: RefKind, + span: SpanData, + ref_id: DefId, +} + +impl From for Ref { + fn from(data: FunctionRefData) -> Ref { + Ref { + kind: RefKind::Function, + span: data.span, + ref_id: data.ref_id, + } + } +} +impl From for Ref { + fn from(data: FunctionCallData) -> Ref { + Ref { + kind: RefKind::Function, + span: data.span, + ref_id: data.ref_id, + } + } +} +impl From for Ref { + fn from(data: MethodCallData) -> Ref { + Ref { + kind: RefKind::Function, + span: data.span, + ref_id: data.ref_id.or(data.decl_id).unwrap_or(null_def_id()), + } + } +} +impl From for Ref { + fn from(data: ModRefData) -> Ref { + Ref { + kind: RefKind::Mod, + span: data.span, + ref_id: data.ref_id.unwrap_or(null_def_id()), + } + } +} +impl From for Ref { + fn from(data: TypeRefData) -> Ref { + Ref { + kind: RefKind::Type, + span: data.span, + ref_id: data.ref_id.unwrap_or(null_def_id()), + } + } +} +impl From for Ref { + fn from(data: VariableRefData) -> Ref { + Ref { + kind: RefKind::Variable, + span: data.span, + ref_id: data.ref_id, + } + } +} + +#[derive(Debug, RustcEncodable)] +struct MacroRef { + span: SpanData, + qualname: String, + callee_span: SpanData, +} + +impl From for MacroRef { + fn from(data: MacroUseData) -> MacroRef { + MacroRef { + span: data.span, + qualname: data.qualname, + callee_span: data.callee_span, + } + } } diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index d62c14d2c57..0a5ac3af714 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -134,6 +134,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { declaration: None, span: sub_span.unwrap(), scope: self.enclosing_scope(item.id), + value: String::new(), // TODO })) } ast::ItemKind::Static(ref typ, mt, ref expr) => { @@ -197,6 +198,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { filter!(self.span_utils, sub_span, item.span, None); Some(Data::EnumData(EnumData { id: item.id, + name: item.ident.to_string(), value: val, span: sub_span.unwrap(), qualname: enum_name, @@ -353,6 +355,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { declaration: decl_id, span: sub_span.unwrap(), scope: self.enclosing_scope(id), + value: String::new(), // TODO }) } From 3e14f011eceea613b395619d41307cf8d87be84f Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 11 May 2016 13:46:39 -0700 Subject: [PATCH 2/3] save-analysis: give better text info in value fields --- src/librustc_save_analysis/dump_visitor.rs | 72 +++++++++++++++++----- src/librustc_save_analysis/json_dumper.rs | 12 ++-- src/librustc_save_analysis/lib.rs | 55 ++++++++++++++--- src/libsyntax/ast.rs | 5 +- 4 files changed, 109 insertions(+), 35 deletions(-) diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 6f84ccc9e36..4d79ddfe8cb 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -39,7 +39,7 @@ use syntax::ast::{self, NodeId, PatKind}; use syntax::codemap::*; use syntax::parse::token::{self, keywords}; use syntax::visit::{self, Visitor}; -use syntax::print::pprust::{path_to_string, ty_to_string}; +use syntax::print::pprust::{path_to_string, ty_to_string, bounds_to_string, generics_to_string}; use syntax::ptr::P; use super::{escape, generated_code, SaveContext, PathCollector}; @@ -388,9 +388,12 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { if let Some(method_data) = self.save_ctxt.get_method_data(id, name, span) { + let sig_str = ::make_signature(&sig.decl, &sig.generics); if body.is_some() { if !self.span.filter_generated(Some(method_data.span), span) { - self.dumper.function(method_data.clone().lower(self.tcx)); + 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 { @@ -401,7 +404,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { span: method_data.span, scope: method_data.scope, qualname: method_data.qualname.clone(), - value: String::new(), // TODO + value: sig_str, }.lower(self.tcx)); } } @@ -540,19 +543,33 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { self.visit_expr(expr); } + // FIXME tuple structs should generate tuple-specific data. fn process_struct(&mut self, item: &ast::Item, def: &ast::VariantData, ty_params: &ast::Generics) { + let name = item.ident.to_string(); let qualname = format!("::{}", self.tcx.node_path_str(item.id)); - let val = self.span.snippet(item.span); 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 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) + } else { + String::new() + }; + if !self.span.filter_generated(sub_span, item.span) { self.dumper.struct_data(StructData { span: sub_span.expect("No span found for struct"), id: item.id, - name: item.ident.to_string(), + name: name, ctor_id: def.id(), qualname: qualname.clone(), scope: self.cur_scope, @@ -589,11 +606,17 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { let mut qualname = enum_data.qualname.clone(); qualname.push_str("::"); qualname.push_str(&name); - let val = self.span.snippet(variant.span); match variant.node.data { - ast::VariantData::Struct(..) => { + ast::VariantData::Struct(ref fields, _) => { let sub_span = self.span.span_for_first_ident(variant.span); + let fields_str = fields.iter() + .enumerate() + .map(|(i, f)| f.ident.map(|i| i.to_string()) + .unwrap_or(i.to_string())) + .collect::>() + .join(", "); + let val = format!("{}::{} {{ {} }}", enum_data.name, name, fields_str); if !self.span.filter_generated(sub_span, variant.span) { self.dumper.struct_variant(StructVariantData { span: sub_span.expect("No span found for struct variant"), @@ -606,13 +629,22 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { }.lower(self.tcx)); } } - _ => { + ref v => { let sub_span = self.span.span_for_first_ident(variant.span); + let mut val = format!("{}::{}", enum_data.name, name); + if let &ast::VariantData::Tuple(ref fields, _) = v { + val.push('('); + val.push_str(&fields.iter() + .map(|f| ty_to_string(&f.ty)) + .collect::>() + .join(", ")); + val.push(')'); + } if !self.span.filter_generated(sub_span, variant.span) { self.dumper.tuple_variant(TupleVariantData { span: sub_span.expect("No span found for tuple variant"), id: variant.node.data.id(), - name: name.to_string(), + name: name, qualname: qualname, type_value: enum_data.qualname.clone(), value: val, @@ -678,14 +710,22 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { generics: &ast::Generics, trait_refs: &ast::TyParamBounds, methods: &[ast::TraitItem]) { + let name = item.ident.to_string(); let qualname = format!("::{}", self.tcx.node_path_str(item.id)); - let val = self.span.snippet(item.span); + let mut val = name.clone(); + if !generics.lifetimes.is_empty() || !generics.ty_params.is_empty() { + val.push_str(&generics_to_string(generics)); + } + if !trait_refs.is_empty() { + val.push_str(": "); + val.push_str(&bounds_to_string(trait_refs)); + } let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Trait); if !self.span.filter_generated(sub_span, item.span) { self.dumper.trait_data(TraitData { span: sub_span.expect("No span found for trait"), id: item.id, - name: item.ident.to_string(), + name: name, qualname: qualname.clone(), scope: self.cur_scope, value: val @@ -915,13 +955,15 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { self.visit_pat(&p); for &(id, ref p, immut, _) in &collector.collected_paths { - let value = if immut == ast::Mutability::Immutable { + let mut value = if immut == ast::Mutability::Immutable { value.to_string() } else { "".to_string() }; let types = self.tcx.node_types(); let typ = types.get(&id).map(|t| t.to_string()).unwrap_or(String::new()); + value.push_str(": "); + value.push_str(&typ); // Get the span only for the name of the variable (I hope the path // is only ever a variable name, but who knows?). let sub_span = self.span.span_for_last_ident(p.span); @@ -1283,13 +1325,13 @@ impl<'v, 'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'v> for DumpVisitor<'l, 'tcx, } ast::ExprKind::ForLoop(ref pattern, ref subexpression, ref block, _) | ast::ExprKind::WhileLet(ref pattern, ref subexpression, ref block, _) => { - let value = self.span.snippet(mk_sp(ex.span.lo, subexpression.span.hi)); + let value = self.span.snippet(subexpression.span); self.process_var_decl(pattern, value); visit::walk_expr(self, subexpression); visit::walk_block(self, block); } ast::ExprKind::IfLet(ref pattern, ref subexpression, ref block, ref opt_else) => { - let value = self.span.snippet(mk_sp(ex.span.lo, subexpression.span.hi)); + let value = self.span.snippet(subexpression.span); self.process_var_decl(pattern, value); visit::walk_expr(self, subexpression); visit::walk_block(self, block); @@ -1379,7 +1421,7 @@ impl<'v, 'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'v> for DumpVisitor<'l, 'tcx, fn visit_local(&mut self, l: &ast::Local) { self.process_macro_use(l.span, l.id); - let value = self.span.snippet(l.span); + let value = l.init.as_ref().map(|i| self.span.snippet(i.span)).unwrap_or(String::new()); self.process_var_decl(&l.pat, value); // Just walk the initialiser and type (don't want to walk the pattern again). diff --git a/src/librustc_save_analysis/json_dumper.rs b/src/librustc_save_analysis/json_dumper.rs index 156a6f5cc97..bdbecdd1d53 100644 --- a/src/librustc_save_analysis/json_dumper.rs +++ b/src/librustc_save_analysis/json_dumper.rs @@ -167,17 +167,17 @@ struct Def { #[derive(Debug, RustcEncodable)] enum DefKind { - // value = type + generics + // value = variant names Enum, - // value = type + generics + // value = enum name + variant name + types Tuple, - // value = type + generics + types + // value = [enum name +] name + fields Struct, - // value = type + generics + // value = signature Trait, // value = type + generics Function, - // No id + // No id, no value. Macro, // value = file_name Mod, @@ -186,8 +186,6 @@ enum DefKind { // value = type and init expression Variable, } -// TODO value for function and method -// TODO none of the values are right. impl From for Def { fn from(data: EnumData) -> Def { diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 0a5ac3af714..8c00a569993 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -52,7 +52,7 @@ use syntax::ast::{self, NodeId, PatKind}; use syntax::codemap::*; use syntax::parse::token::{self, keywords}; use syntax::visit::{self, Visitor}; -use syntax::print::pprust::ty_to_string; +use syntax::print::pprust::{ty_to_string, arg_to_string}; pub use self::csv_dumper::CsvDumper; pub use self::json_dumper::JsonDumper; @@ -122,11 +122,13 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { pub fn get_item_data(&self, item: &ast::Item) -> Option { match item.node { - ast::ItemKind::Fn(..) => { + ast::ItemKind::Fn(ref decl, _, _, _, ref generics, _) => { let name = self.tcx.node_path_str(item.id); let qualname = format!("::{}", name); let sub_span = self.span_utils.sub_span_after_keyword(item.span, keywords::Fn); filter!(self.span_utils, sub_span, item.span, None); + + Some(Data::FunctionData(FunctionData { id: item.id, name: name, @@ -134,7 +136,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { declaration: None, span: sub_span.unwrap(), scope: self.enclosing_scope(item.id), - value: String::new(), // TODO + value: make_signature(decl, generics), })) } ast::ItemKind::Static(ref typ, mt, ref expr) => { @@ -191,17 +193,22 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { filename: filename, })) } - ast::ItemKind::Enum(..) => { - let enum_name = format!("::{}", self.tcx.node_path_str(item.id)); - let val = self.span_utils.snippet(item.span); + ast::ItemKind::Enum(ref def, _) => { + let name = item.ident.to_string(); + let qualname = format!("::{}", self.tcx.node_path_str(item.id)); let sub_span = self.span_utils.sub_span_after_keyword(item.span, keywords::Enum); filter!(self.span_utils, sub_span, item.span, None); + let variants_str = def.variants.iter() + .map(|v| v.node.name.to_string()) + .collect::>() + .join(", "); + let val = format!("{}::{{{}}}", name, variants_str); Some(Data::EnumData(EnumData { id: item.id, - name: item.ident.to_string(), + name: name, value: val, span: sub_span.unwrap(), - qualname: enum_name, + qualname: qualname, scope: self.enclosing_scope(item.id), })) } @@ -355,7 +362,8 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { declaration: decl_id, span: sub_span.unwrap(), scope: self.enclosing_scope(id), - value: String::new(), // TODO + // FIXME you get better data here by using the visitor. + value: String::new(), }) } @@ -640,6 +648,35 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } } +fn make_signature(decl: &ast::FnDecl, generics: &ast::Generics) -> String { + let mut sig = String::new(); + if !generics.lifetimes.is_empty() || !generics.ty_params.is_empty() { + sig.push('<'); + sig.push_str(&generics.lifetimes.iter() + .map(|l| l.lifetime.name.to_string()) + .collect::>() + .join(", ")); + if !generics.lifetimes.is_empty() { + sig.push_str(", "); + } + sig.push_str(&generics.ty_params.iter() + .map(|l| l.ident.to_string()) + .collect::>() + .join(", ")); + sig.push_str("> "); + } + sig.push('('); + sig.push_str(&decl.inputs.iter().map(arg_to_string).collect::>().join(", ")); + sig.push(')'); + match decl.output { + ast::FunctionRetTy::None(_) => sig.push_str(" -> !"), + ast::FunctionRetTy::Default(_) => {} + ast::FunctionRetTy::Ty(ref t) => sig.push_str(&format!(" -> {}", ty_to_string(t))), + } + + sig +} + // An AST visitor for collecting paths from patterns. struct PathCollector { // The Row field identifies the kind of pattern. diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index d1ad330c58c..e9f3472c4a1 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -2030,10 +2030,7 @@ pub enum ItemKind { /// A struct definition, e.g. `struct Foo {x: A}` Struct(VariantData, Generics), /// Represents a Trait Declaration - Trait(Unsafety, - Generics, - TyParamBounds, - Vec), + Trait(Unsafety, Generics, TyParamBounds, Vec), // Default trait implementations /// From 6d6986b87a23ca3fcc62636808ce625fc228bcc0 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 12 May 2016 16:29:07 -0700 Subject: [PATCH 3/3] save-analysis: make DefIds prettier --- src/librustc_save_analysis/json_dumper.rs | 67 ++++++++++++++--------- 1 file changed, 42 insertions(+), 25 deletions(-) diff --git a/src/librustc_save_analysis/json_dumper.rs b/src/librustc_save_analysis/json_dumper.rs index bdbecdd1d53..610a9ac2ad6 100644 --- a/src/librustc_save_analysis/json_dumper.rs +++ b/src/librustc_save_analysis/json_dumper.rs @@ -36,9 +36,9 @@ impl<'b, W: Write> Drop for JsonDumper<'b, W> { } macro_rules! impl_fn { - ($fn_name: ident, $data_type: ident, $bin: ident) => { + ($fn_name: ident, $data_type: ident, $bucket: ident) => { fn $fn_name(&mut self, data: $data_type) { - self.result.$bin.push(From::from(data)); + self.result.$bucket.push(From::from(data)); } } } @@ -105,10 +105,27 @@ impl Analysis { } } +// 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: DefId, + id: Id, span: SpanData, name: String, value: String, @@ -125,7 +142,7 @@ impl From for Import { fn from(data: ExternCrateData) -> Import { Import { kind: ImportKind::ExternCrate, - id: data.id, + id: From::from(data.id), span: data.span, name: data.name, value: String::new(), @@ -136,7 +153,7 @@ impl From for Import { fn from(data: UseData) -> Import { Import { kind: ImportKind::Use, - id: data.id, + id: From::from(data.id), span: data.span, name: data.name, value: String::new(), @@ -147,7 +164,7 @@ impl From for Import { fn from(data: UseGlobData) -> Import { Import { kind: ImportKind::GlobUse, - id: data.id, + id: From::from(data.id), span: data.span, name: "*".to_owned(), value: data.names.join(", "), @@ -158,7 +175,7 @@ impl From for Import { #[derive(Debug, RustcEncodable)] struct Def { kind: DefKind, - id: DefId, + id: Id, span: SpanData, name: String, qualname: String, @@ -191,7 +208,7 @@ impl From for Def { fn from(data: EnumData) -> Def { Def { kind: DefKind::Enum, - id: data.id, + id: From::from(data.id), span: data.span, name: data.name, qualname: data.qualname, @@ -204,7 +221,7 @@ impl From for Def { fn from(data: TupleVariantData) -> Def { Def { kind: DefKind::Tuple, - id: data.id, + id: From::from(data.id), span: data.span, name: data.name, qualname: data.qualname, @@ -216,7 +233,7 @@ impl From for Def { fn from(data: StructVariantData) -> Def { Def { kind: DefKind::Struct, - id: data.id, + id: From::from(data.id), span: data.span, name: data.name, qualname: data.qualname, @@ -228,7 +245,7 @@ impl From for Def { fn from(data: StructData) -> Def { Def { kind: DefKind::Struct, - id: data.id, + id: From::from(data.id), span: data.span, name: data.name, qualname: data.qualname, @@ -240,7 +257,7 @@ impl From for Def { fn from(data: TraitData) -> Def { Def { kind: DefKind::Trait, - id: data.id, + id: From::from(data.id), span: data.span, name: data.name, qualname: data.qualname, @@ -252,7 +269,7 @@ impl From for Def { fn from(data: FunctionData) -> Def { Def { kind: DefKind::Function, - id: data.id, + id: From::from(data.id), span: data.span, name: data.name, qualname: data.qualname, @@ -264,7 +281,7 @@ impl From for Def { fn from(data: MethodData) -> Def { Def { kind: DefKind::Function, - id: data.id, + id: From::from(data.id), span: data.span, name: data.name, qualname: data.qualname, @@ -276,7 +293,7 @@ impl From for Def { fn from(data: MacroData) -> Def { Def { kind: DefKind::Macro, - id: null_def_id(), + id: From::from(null_def_id()), span: data.span, name: data.name, qualname: data.qualname, @@ -288,7 +305,7 @@ impl From for Def { fn from(data:ModData) -> Def { Def { kind: DefKind::Mod, - id: data.id, + id: From::from(data.id), span: data.span, name: data.name, qualname: data.qualname, @@ -300,7 +317,7 @@ impl From for Def { fn from(data: TypeDefData) -> Def { Def { kind: DefKind::Type, - id: data.id, + id: From::from(data.id), span: data.span, name: data.name, qualname: data.qualname, @@ -312,7 +329,7 @@ impl From for Def { fn from(data: VariableData) -> Def { Def { kind: DefKind::Variable, - id: data.id, + id: From::from(data.id), span: data.span, name: data.name, qualname: data.qualname, @@ -333,7 +350,7 @@ enum RefKind { struct Ref { kind: RefKind, span: SpanData, - ref_id: DefId, + ref_id: Id, } impl From for Ref { @@ -341,7 +358,7 @@ impl From for Ref { Ref { kind: RefKind::Function, span: data.span, - ref_id: data.ref_id, + ref_id: From::from(data.ref_id), } } } @@ -350,7 +367,7 @@ impl From for Ref { Ref { kind: RefKind::Function, span: data.span, - ref_id: data.ref_id, + ref_id: From::from(data.ref_id), } } } @@ -359,7 +376,7 @@ impl From for Ref { Ref { kind: RefKind::Function, span: data.span, - ref_id: data.ref_id.or(data.decl_id).unwrap_or(null_def_id()), + ref_id: From::from(data.ref_id.or(data.decl_id).unwrap_or(null_def_id())), } } } @@ -368,7 +385,7 @@ impl From for Ref { Ref { kind: RefKind::Mod, span: data.span, - ref_id: data.ref_id.unwrap_or(null_def_id()), + ref_id: From::from(data.ref_id.unwrap_or(null_def_id())), } } } @@ -377,7 +394,7 @@ impl From for Ref { Ref { kind: RefKind::Type, span: data.span, - ref_id: data.ref_id.unwrap_or(null_def_id()), + ref_id: From::from(data.ref_id.unwrap_or(null_def_id())), } } } @@ -386,7 +403,7 @@ impl From for Ref { Ref { kind: RefKind::Variable, span: data.span, - ref_id: data.ref_id, + ref_id: From::from(data.ref_id), } } }