From c28374ef0b1b787ba039f55341caae88081ccc78 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Sat, 11 Jun 2016 12:23:57 +0200 Subject: [PATCH 1/2] save-analysis: some refinements to JSON data Split variable and function kinds to give more information. Give children for methods, structs, enums, and traits. --- src/librustc_save_analysis/data.rs | 18 +++++++++-- src/librustc_save_analysis/dump_visitor.rs | 19 +++++++---- src/librustc_save_analysis/external_data.rs | 18 ++++++++--- src/librustc_save_analysis/json_dumper.rs | 35 +++++++++++++++++---- src/librustc_save_analysis/lib.rs | 5 +++ 5 files changed, 77 insertions(+), 18 deletions(-) diff --git a/src/librustc_save_analysis/data.rs b/src/librustc_save_analysis/data.rs index 2275a1c5c65..94e2a52c6ad 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. @@ -223,6 +225,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 +245,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 +267,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 +322,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 +331,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 216d188a503..a6bc6e180ac 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -356,6 +356,7 @@ fn process_formals(&mut self, formals: &Vec, qualname: &str) { 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)), @@ -519,6 +520,7 @@ fn process_const(&mut self, 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 +544,18 @@ fn process_struct(&mut self, 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 +566,8 @@ fn process_struct(&mut self, ctor_id: def.id(), qualname: qualname.clone(), scope: self.cur_scope, - value: val + value: val, + fields: fields, }.lower(self.tcx)); } @@ -718,7 +722,8 @@ fn process_trait(&mut self, 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 +963,7 @@ fn process_var_decl(&mut self, p: &ast::Pat, value: String) { 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 +1372,7 @@ fn visit_arm(&mut self, arm: &ast::Arm) { 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 dc51c41f296..3c59765e6c1 100644 --- a/src/librustc_save_analysis/external_data.rs +++ b/src/librustc_save_analysis/external_data.rs @@ -14,7 +14,7 @@ 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 @@ fn lower(self, tcx: TyCtxt) -> 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(), } } } @@ -345,6 +347,7 @@ pub struct ModData { pub span: SpanData, pub scope: DefId, pub filename: String, + pub items: Vec, } impl Lower for data::ModData { @@ -358,6 +361,7 @@ fn lower(self, tcx: TyCtxt) -> 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 +396,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 +411,8 @@ fn lower(self, tcx: TyCtxt) -> 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 +451,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 +466,7 @@ fn lower(self, tcx: TyCtxt) -> 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 +593,7 @@ fn lower(self, tcx: TyCtxt) -> 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 +607,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 610a9ac2ad6..f1ca127667c 100644 --- a/src/librustc_save_analysis/json_dumper.rs +++ b/src/librustc_save_analysis/json_dumper.rs @@ -13,8 +13,9 @@ 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,7 @@ struct Def { name: String, qualname: String, value: String, + children: Vec, } #[derive(Debug, RustcEncodable)] @@ -194,14 +196,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 +220,7 @@ fn from(data: EnumData) -> Def { name: data.name, qualname: data.qualname, value: data.value, + children: data.variants.into_iter().map(|id| From::from(id)).collect(), } } } @@ -226,6 +234,7 @@ fn from(data: TupleVariantData) -> Def { name: data.name, qualname: data.qualname, value: data.value, + children: vec![], } } } @@ -238,6 +247,7 @@ fn from(data: StructVariantData) -> Def { name: data.name, qualname: data.qualname, value: data.value, + children: vec![], } } } @@ -250,6 +260,7 @@ fn from(data: StructData) -> Def { name: data.name, qualname: data.qualname, value: data.value, + children: data.fields.into_iter().map(|id| From::from(id)).collect(), } } } @@ -262,6 +273,7 @@ fn from(data: TraitData) -> Def { name: data.name, qualname: data.qualname, value: data.value, + children: data.items.into_iter().map(|id| From::from(id)).collect(), } } } @@ -274,18 +286,20 @@ fn from(data: FunctionData) -> Def { name: data.name, qualname: data.qualname, value: data.value, + children: vec![], } } } 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![], } } } @@ -298,6 +312,7 @@ fn from(data: MacroData) -> Def { name: data.name, qualname: data.qualname, value: String::new(), + children: vec![], } } } @@ -310,6 +325,7 @@ fn from(data:ModData) -> Def { name: data.name, qualname: data.qualname, value: data.filename, + children: data.items.into_iter().map(|id| From::from(id)).collect(), } } } @@ -322,18 +338,25 @@ fn from(data: TypeDefData) -> Def { name: data.name, qualname: data.qualname, value: data.value, + children: vec![], } } } 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![], } } } diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 27f15756a91..33351338160 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -153,6 +153,7 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option { 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 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option { 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 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option { 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 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option { 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 @@ pub fn get_field_data(&self, field: &ast::StructField, 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(), From a835d7487cc729a2a64149709229fb62af2d78fc Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 16 Jun 2016 11:28:39 +0100 Subject: [PATCH 2/2] save-analysis: add a decl_id for methods This is non-null if the method is in a (non-inherent) impl and in that case will be the id for the method declaration in the implemented trait. --- src/librustc_save_analysis/data.rs | 1 + src/librustc_save_analysis/dump_visitor.rs | 52 ++++++++++++++------- src/librustc_save_analysis/external_data.rs | 2 + src/librustc_save_analysis/json_dumper.rs | 12 +++++ 4 files changed, 50 insertions(+), 17 deletions(-) diff --git a/src/librustc_save_analysis/data.rs b/src/librustc_save_analysis/data.rs index 94e2a52c6ad..15aaa77cc35 100644 --- a/src/librustc_save_analysis/data.rs +++ b/src/librustc_save_analysis/data.rs @@ -214,6 +214,7 @@ pub struct MethodData { pub span: Span, pub scope: NodeId, pub value: String, + pub decl_id: Option, } /// Data for modules. diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index a6bc6e180ac..56c7436a8fe 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::*; @@ -381,24 +381,42 @@ fn process_method(&mut self, 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); } diff --git a/src/librustc_save_analysis/external_data.rs b/src/librustc_save_analysis/external_data.rs index 3c59765e6c1..7efd2624561 100644 --- a/src/librustc_save_analysis/external_data.rs +++ b/src/librustc_save_analysis/external_data.rs @@ -321,6 +321,7 @@ pub struct MethodData { pub span: SpanData, pub scope: DefId, pub value: String, + pub decl_id: Option, } impl Lower for data::MethodData { @@ -334,6 +335,7 @@ fn lower(self, tcx: TyCtxt) -> MethodData { id: make_def_id(self.id, &tcx.map), qualname: self.qualname, value: self.value, + decl_id: self.decl_id, } } } diff --git a/src/librustc_save_analysis/json_dumper.rs b/src/librustc_save_analysis/json_dumper.rs index f1ca127667c..b1955cbd7b8 100644 --- a/src/librustc_save_analysis/json_dumper.rs +++ b/src/librustc_save_analysis/json_dumper.rs @@ -182,6 +182,7 @@ struct Def { qualname: String, value: String, children: Vec, + decl_id: Option, } #[derive(Debug, RustcEncodable)] @@ -221,6 +222,7 @@ fn from(data: EnumData) -> Def { qualname: data.qualname, value: data.value, children: data.variants.into_iter().map(|id| From::from(id)).collect(), + decl_id: None, } } } @@ -235,6 +237,7 @@ fn from(data: TupleVariantData) -> Def { qualname: data.qualname, value: data.value, children: vec![], + decl_id: None, } } } @@ -248,6 +251,7 @@ fn from(data: StructVariantData) -> Def { qualname: data.qualname, value: data.value, children: vec![], + decl_id: None, } } } @@ -261,6 +265,7 @@ fn from(data: StructData) -> Def { qualname: data.qualname, value: data.value, children: data.fields.into_iter().map(|id| From::from(id)).collect(), + decl_id: None, } } } @@ -274,6 +279,7 @@ fn from(data: TraitData) -> Def { qualname: data.qualname, value: data.value, children: data.items.into_iter().map(|id| From::from(id)).collect(), + decl_id: None, } } } @@ -287,6 +293,7 @@ fn from(data: FunctionData) -> Def { qualname: data.qualname, value: data.value, children: vec![], + decl_id: None, } } } @@ -300,6 +307,7 @@ fn from(data: MethodData) -> Def { qualname: data.qualname, value: data.value, children: vec![], + decl_id: data.decl_id.map(|id| From::from(id)), } } } @@ -313,6 +321,7 @@ fn from(data: MacroData) -> Def { qualname: data.qualname, value: String::new(), children: vec![], + decl_id: None, } } } @@ -326,6 +335,7 @@ fn from(data:ModData) -> Def { qualname: data.qualname, value: data.filename, children: data.items.into_iter().map(|id| From::from(id)).collect(), + decl_id: None, } } } @@ -339,6 +349,7 @@ fn from(data: TypeDefData) -> Def { qualname: data.qualname, value: data.value, children: vec![], + decl_id: None, } } } @@ -357,6 +368,7 @@ fn from(data: VariableData) -> Def { qualname: data.qualname, value: data.value, children: vec![], + decl_id: None, } } }