save-analysis: give better text info in value fields
This commit is contained in:
parent
a0a987722e
commit
3e14f011ec
@ -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::<Vec<_>>()
|
||||
.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::<Vec<_>>()
|
||||
.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::<Vec<_>>()
|
||||
.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 {
|
||||
"<mutable>".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).
|
||||
|
@ -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<EnumData> for Def {
|
||||
fn from(data: EnumData) -> Def {
|
||||
|
@ -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<Data> {
|
||||
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::<Vec<_>>()
|
||||
.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::<Vec<_>>()
|
||||
.join(", "));
|
||||
if !generics.lifetimes.is_empty() {
|
||||
sig.push_str(", ");
|
||||
}
|
||||
sig.push_str(&generics.ty_params.iter()
|
||||
.map(|l| l.ident.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join(", "));
|
||||
sig.push_str("> ");
|
||||
}
|
||||
sig.push('(');
|
||||
sig.push_str(&decl.inputs.iter().map(arg_to_string).collect::<Vec<_>>().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.
|
||||
|
@ -2030,10 +2030,7 @@ pub enum ItemKind {
|
||||
/// A struct definition, e.g. `struct Foo<A> {x: A}`
|
||||
Struct(VariantData, Generics),
|
||||
/// Represents a Trait Declaration
|
||||
Trait(Unsafety,
|
||||
Generics,
|
||||
TyParamBounds,
|
||||
Vec<TraitItem>),
|
||||
Trait(Unsafety, Generics, TyParamBounds, Vec<TraitItem>),
|
||||
|
||||
// Default trait implementations
|
||||
///
|
||||
|
Loading…
x
Reference in New Issue
Block a user