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};
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 {
span: method_data.span,
scope: method_data.scope,
qualname: method_data.qualname.clone(),
- value: String::new(), // TODO
+ value: sig_str,
}.lower(self.tcx));
}
}
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,
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"),
}.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,
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
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);
}
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);
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).
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;
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,
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) => {
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),
}))
}
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(),
})
}
}
}
+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.