diff --git a/src/librustc_save_analysis/data.rs b/src/librustc_save_analysis/data.rs index a58cce0745f..5f6e65e289f 100644 --- a/src/librustc_save_analysis/data.rs +++ b/src/librustc_save_analysis/data.rs @@ -134,6 +134,7 @@ pub struct EnumData { pub scope: NodeId, pub variants: Vec, pub visibility: Visibility, + pub docs: String, } /// Data for extern crates. @@ -167,6 +168,7 @@ pub struct FunctionData { pub value: String, pub visibility: Visibility, pub parent: Option, + pub docs: String, } /// Data about a function call. @@ -213,6 +215,7 @@ pub struct MacroData { pub span: Span, pub name: String, pub qualname: String, + pub docs: String, } /// Data about a macro use. @@ -248,6 +251,7 @@ pub struct MethodData { pub value: String, pub decl_id: Option, pub visibility: Visibility, + pub docs: String, } /// Data for modules. @@ -261,6 +265,7 @@ pub struct ModData { pub filename: String, pub items: Vec, pub visibility: Visibility, + pub docs: String, } /// Data for a reference to a module. @@ -283,6 +288,7 @@ pub struct StructData { pub value: String, pub fields: Vec, pub visibility: Visibility, + pub docs: String, } #[derive(Debug, RustcEncodable)] @@ -295,6 +301,7 @@ pub struct StructVariantData { pub value: String, pub scope: NodeId, pub parent: Option, + pub docs: String, } #[derive(Debug, RustcEncodable)] @@ -307,6 +314,7 @@ pub struct TraitData { pub value: String, pub items: Vec, pub visibility: Visibility, + pub docs: String, } #[derive(Debug, RustcEncodable)] @@ -319,6 +327,7 @@ pub struct TupleVariantData { pub value: String, pub scope: NodeId, pub parent: Option, + pub docs: String, } /// Data for a typedef. @@ -331,6 +340,7 @@ pub struct TypeDefData { pub value: String, pub visibility: Visibility, pub parent: Option, + pub docs: String, } /// Data for a reference to a type or trait. @@ -374,6 +384,7 @@ pub struct VariableData { pub value: String, pub type_value: String, pub visibility: Visibility, + pub docs: String, } #[derive(Debug, RustcEncodable)] diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index ebd0bdc71d7..d8e2324559c 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -36,7 +36,7 @@ use rustc::ty::{self, TyCtxt, ImplOrTraitItem, ImplOrTraitItemContainer}; use std::collections::HashSet; use std::hash::*; -use syntax::ast::{self, NodeId, PatKind}; +use syntax::ast::{self, NodeId, PatKind, Attribute}; use syntax::parse::token::{self, keywords}; use syntax::visit::{self, Visitor}; use syntax::print::pprust::{path_to_string, ty_to_string, bounds_to_string, generics_to_string}; @@ -44,7 +44,7 @@ use syntax::ptr::P; use syntax::codemap::Spanned; use syntax_pos::*; -use super::{escape, generated_code, SaveContext, PathCollector}; +use super::{escape, generated_code, SaveContext, PathCollector, docs_for_attrs}; use super::data::*; use super::dump::Dump; use super::external_data::Lower; @@ -368,6 +368,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { scope: 0, parent: None, visibility: Visibility::Inherited, + docs: String::new(), }.lower(self.tcx)); } } @@ -380,6 +381,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { id: ast::NodeId, name: ast::Name, vis: Visibility, + attrs: &[Attribute], span: Span) { debug!("process_method: {}:{}", id, name); @@ -421,6 +423,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { value: sig_str, decl_id: decl_id, visibility: vis, + docs: docs_for_attrs(attrs), }.lower(self.tcx)); } @@ -491,6 +494,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { value: String::new(), visibility: Visibility::Inherited, parent: None, + docs: String::new(), }.lower(self.tcx)); } } @@ -541,7 +545,8 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { typ: &ast::Ty, expr: &ast::Expr, parent_id: NodeId, - vis: Visibility) { + vis: Visibility, + attrs: &[Attribute]) { let qualname = format!("::{}", self.tcx.node_path_str(id)); let sub_span = self.span.sub_span_after_keyword(span, keywords::Const); @@ -558,6 +563,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { scope: self.cur_scope, parent: Some(parent_id), visibility: vis, + docs: docs_for_attrs(attrs), }.lower(self.tcx)); } @@ -600,6 +606,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { value: val, fields: fields, visibility: From::from(&item.vis), + docs: docs_for_attrs(&item.attrs), }.lower(self.tcx)); } @@ -653,6 +660,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { value: val, scope: enum_data.scope, parent: Some(item.id), + docs: docs_for_attrs(&variant.node.attrs), }.lower(self.tcx)); } } @@ -677,6 +685,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { value: val, scope: enum_data.scope, parent: Some(item.id), + docs: docs_for_attrs(&variant.node.attrs), }.lower(self.tcx)); } } @@ -759,6 +768,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { value: val, items: methods.iter().map(|i| i.id).collect(), visibility: From::from(&item.vis), + docs: docs_for_attrs(&item.attrs), }.lower(self.tcx)); } @@ -1015,6 +1025,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { scope: 0, parent: None, visibility: Visibility::Inherited, + docs: String::new(), }.lower(self.tcx)); } } @@ -1044,7 +1055,9 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { self.dumper.macro_data(MacroData { span: sub_span, name: data.name.clone(), - qualname: qualname.clone() + qualname: qualname.clone(), + // FIXME where do macro docs come from? + docs: String::new(), }.lower(self.tcx)); } } @@ -1057,7 +1070,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { qualname: qualname, scope: data.scope, callee_span: data.callee_span, - imported: data.imported + imported: data.imported, }.lower(self.tcx)); } } @@ -1073,7 +1086,8 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { &ty, &expr, trait_id, - Visibility::Public); + Visibility::Public, + &trait_item.attrs); } ast::TraitItemKind::Method(ref sig, ref body) => { self.process_method(sig, @@ -1081,6 +1095,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { trait_item.id, trait_item.ident.name, Visibility::Public, + &trait_item.attrs, trait_item.span); } ast::TraitItemKind::Const(_, None) | @@ -1099,7 +1114,8 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { &ty, &expr, impl_id, - From::from(&impl_item.vis)); + From::from(&impl_item.vis), + &impl_item.attrs); } ast::ImplItemKind::Method(ref sig, ref body) => { self.process_method(sig, @@ -1107,6 +1123,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { impl_item.id, impl_item.ident.name, From::from(&impl_item.vis), + &impl_item.attrs, impl_item.span); } ast::ImplItemKind::Type(_) | @@ -1248,6 +1265,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor for DumpVisitor<'l, 'tcx, 'll, D> value: value, visibility: From::from(&item.vis), parent: None, + docs: docs_for_attrs(&item.attrs), }.lower(self.tcx)); } @@ -1417,11 +1435,15 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor for DumpVisitor<'l, 'tcx, 'll, D> for &(id, ref p, immut, ref_kind) in &collector.collected_paths { match self.tcx.expect_def(id) { Def::Local(_, id) => { - let value = if immut == ast::Mutability::Immutable { + let mut value = if immut == ast::Mutability::Immutable { self.span.snippet(p.span).to_string() } else { "".to_string() }; + let typ = self.tcx.node_types() + .get(&id).map(|t| t.to_string()).unwrap_or(String::new()); + value.push_str(": "); + value.push_str(&typ); assert!(p.segments.len() == 1, "qualified path for local variable def in arm"); @@ -1433,10 +1455,11 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor for DumpVisitor<'l, 'tcx, 'll, D> name: path_to_string(p), qualname: format!("{}${}", path_to_string(p), id), value: value, - type_value: String::new(), + type_value: typ, scope: 0, parent: None, visibility: Visibility::Inherited, + docs: String::new(), }.lower(self.tcx)); } } diff --git a/src/librustc_save_analysis/external_data.rs b/src/librustc_save_analysis/external_data.rs index 4333c6dd18e..3642346582b 100644 --- a/src/librustc_save_analysis/external_data.rs +++ b/src/librustc_save_analysis/external_data.rs @@ -93,6 +93,7 @@ pub struct EnumData { pub scope: DefId, pub variants: Vec, pub visibility: Visibility, + pub docs: String, } impl Lower for data::EnumData { @@ -108,6 +109,7 @@ impl Lower for data::EnumData { scope: make_def_id(self.scope, &tcx.map), variants: self.variants.into_iter().map(|id| make_def_id(id, &tcx.map)).collect(), visibility: self.visibility, + docs: self.docs, } } } @@ -170,6 +172,7 @@ pub struct FunctionData { pub value: String, pub visibility: Visibility, pub parent: Option, + pub docs: String, } impl Lower for data::FunctionData { @@ -186,6 +189,7 @@ impl Lower for data::FunctionData { value: self.value, visibility: self.visibility, parent: self.parent.map(|id| make_def_id(id, &tcx.map)), + docs: self.docs, } } } @@ -257,6 +261,7 @@ pub struct MacroData { pub span: SpanData, pub name: String, pub qualname: String, + pub docs: String, } impl Lower for data::MacroData { @@ -267,6 +272,7 @@ impl Lower for data::MacroData { span: SpanData::from_span(self.span, tcx.sess.codemap()), name: self.name, qualname: self.qualname, + docs: self.docs, } } } @@ -330,7 +336,8 @@ pub struct MethodData { pub value: String, pub decl_id: Option, pub visibility: Visibility, - pub parent: Option + pub parent: Option, + pub docs: String, } impl Lower for data::MethodData { @@ -347,6 +354,7 @@ impl Lower for data::MethodData { decl_id: self.decl_id, visibility: self.visibility, parent: Some(make_def_id(self.scope, &tcx.map)), + docs: self.docs, } } } @@ -362,6 +370,7 @@ pub struct ModData { pub filename: String, pub items: Vec, pub visibility: Visibility, + pub docs: String, } impl Lower for data::ModData { @@ -377,6 +386,7 @@ impl Lower for data::ModData { filename: self.filename, items: self.items.into_iter().map(|id| make_def_id(id, &tcx.map)).collect(), visibility: self.visibility, + docs: self.docs, } } } @@ -414,6 +424,7 @@ pub struct StructData { pub value: String, pub fields: Vec, pub visibility: Visibility, + pub docs: String, } impl Lower for data::StructData { @@ -430,6 +441,7 @@ impl Lower for data::StructData { value: self.value, fields: self.fields.into_iter().map(|id| make_def_id(id, &tcx.map)).collect(), visibility: self.visibility, + docs: self.docs, } } } @@ -444,6 +456,7 @@ pub struct StructVariantData { pub value: String, pub scope: DefId, pub parent: Option, + pub docs: String, } impl Lower for data::StructVariantData { @@ -459,6 +472,7 @@ impl Lower for data::StructVariantData { value: self.value, scope: make_def_id(self.scope, &tcx.map), parent: self.parent.map(|id| make_def_id(id, &tcx.map)), + docs: self.docs, } } } @@ -473,6 +487,7 @@ pub struct TraitData { pub value: String, pub items: Vec, pub visibility: Visibility, + pub docs: String, } impl Lower for data::TraitData { @@ -488,6 +503,7 @@ impl Lower for data::TraitData { value: self.value, items: self.items.into_iter().map(|id| make_def_id(id, &tcx.map)).collect(), visibility: self.visibility, + docs: self.docs, } } } @@ -502,6 +518,7 @@ pub struct TupleVariantData { pub value: String, pub scope: DefId, pub parent: Option, + pub docs: String, } impl Lower for data::TupleVariantData { @@ -517,6 +534,7 @@ impl Lower for data::TupleVariantData { value: self.value, scope: make_def_id(self.scope, &tcx.map), parent: self.parent.map(|id| make_def_id(id, &tcx.map)), + docs: self.docs, } } } @@ -531,6 +549,7 @@ pub struct TypeDefData { pub value: String, pub visibility: Visibility, pub parent: Option, + pub docs: String, } impl Lower for data::TypeDefData { @@ -545,6 +564,7 @@ impl Lower for data::TypeDefData { value: self.value, visibility: self.visibility, parent: self.parent.map(|id| make_def_id(id, &tcx.map)), + docs: self.docs, } } } @@ -632,6 +652,7 @@ pub struct VariableData { pub type_value: String, pub parent: Option, pub visibility: Visibility, + pub docs: String, } impl Lower for data::VariableData { @@ -649,6 +670,7 @@ impl Lower for data::VariableData { type_value: self.type_value, parent: self.parent.map(|id| make_def_id(id, &tcx.map)), visibility: self.visibility, + docs: self.docs, } } } diff --git a/src/librustc_save_analysis/json_api_dumper.rs b/src/librustc_save_analysis/json_api_dumper.rs index 874babb907e..78eaa65872a 100644 --- a/src/librustc_save_analysis/json_api_dumper.rs +++ b/src/librustc_save_analysis/json_api_dumper.rs @@ -16,6 +16,8 @@ use rustc_serialize::json::as_json; use external_data::*; use data::{VariableKind, Visibility}; use dump::Dump; +use super::Format; + // A dumper to dump a restricted set of JSON information, designed for use with // libraries distributed without their source. Clients are likely to use type @@ -81,17 +83,25 @@ impl<'b, W: Write + 'b> Dump for JsonApiDumper<'b, W> { #[derive(Debug, RustcEncodable)] struct Analysis { + kind: Format, prelude: Option, imports: Vec, defs: Vec, + // These two fields are dummies so that clients can parse the two kinds of + // JSON data in the same way. + refs: Vec<()>, + macro_refs: Vec<()>, } impl Analysis { fn new() -> Analysis { Analysis { + kind: Format::JsonApi, prelude: None, imports: vec![], defs: vec![], + refs: vec![], + macro_refs: vec![], } } } @@ -168,6 +178,7 @@ struct Def { parent: Option, children: Vec, decl_id: Option, + docs: String, } #[derive(Debug, RustcEncodable)] @@ -209,6 +220,7 @@ impl From for Option { parent: None, children: data.variants.into_iter().map(|id| From::from(id)).collect(), decl_id: None, + docs: data.docs, }), _ => None, } @@ -227,6 +239,7 @@ impl From for Option { parent: data.parent.map(|id| From::from(id)), children: vec![], decl_id: None, + docs: data.docs, }) } } @@ -242,6 +255,7 @@ impl From for Option { parent: data.parent.map(|id| From::from(id)), children: vec![], decl_id: None, + docs: data.docs, }) } } @@ -258,6 +272,7 @@ impl From for Option { parent: None, children: data.fields.into_iter().map(|id| From::from(id)).collect(), decl_id: None, + docs: data.docs, }), _ => None, } @@ -276,6 +291,7 @@ impl From for Option { children: data.items.into_iter().map(|id| From::from(id)).collect(), parent: None, decl_id: None, + docs: data.docs, }), _ => None, } @@ -294,6 +310,7 @@ impl From for Option { children: vec![], parent: data.parent.map(|id| From::from(id)), decl_id: None, + docs: data.docs, }), _ => None, } @@ -312,6 +329,7 @@ impl From for Option { children: vec![], parent: data.parent.map(|id| From::from(id)), decl_id: data.decl_id.map(|id| From::from(id)), + docs: data.docs, }), _ => None, } @@ -329,6 +347,7 @@ impl From for Option { children: vec![], parent: None, decl_id: None, + docs: data.docs, }) } } @@ -345,6 +364,7 @@ impl From for Option { children: data.items.into_iter().map(|id| From::from(id)).collect(), parent: None, decl_id: None, + docs: data.docs, }), _ => None, } @@ -363,6 +383,7 @@ impl From for Option { children: vec![], parent: data.parent.map(|id| From::from(id)), decl_id: None, + docs: String::new(), }), _ => None, } @@ -386,6 +407,7 @@ impl From for Option { children: vec![], parent: data.parent.map(|id| From::from(id)), decl_id: None, + docs: data.docs, }), _ => None, } diff --git a/src/librustc_save_analysis/json_dumper.rs b/src/librustc_save_analysis/json_dumper.rs index b1955cbd7b8..75abff8d37e 100644 --- a/src/librustc_save_analysis/json_dumper.rs +++ b/src/librustc_save_analysis/json_dumper.rs @@ -16,6 +16,7 @@ use rustc_serialize::json::as_json; use external_data::*; use data::VariableKind; use dump::Dump; +use super::Format; pub struct JsonDumper<'b, W: Write + 'b> { output: &'b mut W, @@ -87,6 +88,7 @@ impl<'b, W: Write + 'b> Dump for JsonDumper<'b, W> { #[derive(Debug, RustcEncodable)] struct Analysis { + kind: Format, prelude: Option, imports: Vec, defs: Vec, @@ -97,6 +99,7 @@ struct Analysis { impl Analysis { fn new() -> Analysis { Analysis { + kind: Format::Json, prelude: None, imports: vec![], defs: vec![], @@ -183,6 +186,7 @@ struct Def { value: String, children: Vec, decl_id: Option, + docs: String, } #[derive(Debug, RustcEncodable)] @@ -223,6 +227,7 @@ impl From for Def { value: data.value, children: data.variants.into_iter().map(|id| From::from(id)).collect(), decl_id: None, + docs: data.docs, } } } @@ -238,6 +243,7 @@ impl From for Def { value: data.value, children: vec![], decl_id: None, + docs: data.docs, } } } @@ -252,6 +258,7 @@ impl From for Def { value: data.value, children: vec![], decl_id: None, + docs: data.docs, } } } @@ -266,6 +273,7 @@ impl From for Def { value: data.value, children: data.fields.into_iter().map(|id| From::from(id)).collect(), decl_id: None, + docs: data.docs, } } } @@ -280,6 +288,7 @@ impl From for Def { value: data.value, children: data.items.into_iter().map(|id| From::from(id)).collect(), decl_id: None, + docs: data.docs, } } } @@ -294,6 +303,7 @@ impl From for Def { value: data.value, children: vec![], decl_id: None, + docs: data.docs, } } } @@ -308,6 +318,7 @@ impl From for Def { value: data.value, children: vec![], decl_id: data.decl_id.map(|id| From::from(id)), + docs: data.docs, } } } @@ -322,6 +333,7 @@ impl From for Def { value: String::new(), children: vec![], decl_id: None, + docs: data.docs, } } } @@ -336,6 +348,7 @@ impl From for Def { value: data.filename, children: data.items.into_iter().map(|id| From::from(id)).collect(), decl_id: None, + docs: data.docs, } } } @@ -350,6 +363,7 @@ impl From for Def { value: data.value, children: vec![], decl_id: None, + docs: String::new(), } } } @@ -366,9 +380,10 @@ impl From for Def { span: data.span, name: data.name, qualname: data.qualname, - value: data.value, + value: data.type_value, children: vec![], decl_id: None, + docs: data.docs, } } } diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 04cd72ac2d3..354709ac9e1 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -30,6 +30,7 @@ extern crate serialize as rustc_serialize; extern crate syntax_pos; + mod csv_dumper; mod json_api_dumper; mod json_dumper; @@ -51,8 +52,9 @@ use std::env; use std::fs::{self, File}; use std::path::{Path, PathBuf}; -use syntax::ast::{self, NodeId, PatKind}; -use syntax::parse::token::{self, keywords}; +use syntax::ast::{self, NodeId, PatKind, Attribute}; +use syntax::parse::lexer::comments::strip_doc_comment_decoration; +use syntax::parse::token::{self, keywords, InternedString}; use syntax::visit::{self, Visitor}; use syntax::print::pprust::{ty_to_string, arg_to_string}; use syntax::codemap::MacroAttribute; @@ -143,6 +145,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { value: make_signature(decl, generics), visibility: From::from(&item.vis), parent: None, + docs: docs_for_attrs(&item.attrs), })) } ast::ItemKind::Static(ref typ, mt, ref expr) => { @@ -169,6 +172,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { value: value, type_value: ty_to_string(&typ), visibility: From::from(&item.vis), + docs: docs_for_attrs(&item.attrs), })) } ast::ItemKind::Const(ref typ, ref expr) => { @@ -186,6 +190,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { value: self.span_utils.snippet(expr.span), type_value: ty_to_string(&typ), visibility: From::from(&item.vis), + docs: docs_for_attrs(&item.attrs), })) } ast::ItemKind::Mod(ref m) => { @@ -205,6 +210,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { filename: filename, items: m.items.iter().map(|i| i.id).collect(), visibility: From::from(&item.vis), + docs: docs_for_attrs(&item.attrs), })) } ast::ItemKind::Enum(ref def, _) => { @@ -226,6 +232,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { scope: self.enclosing_scope(item.id), variants: def.variants.iter().map(|v| v.node.data.id()).collect(), visibility: From::from(&item.vis), + docs: docs_for_attrs(&item.attrs), })) } ast::ItemKind::Impl(.., ref trait_ref, ref typ, _) => { @@ -292,6 +299,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { value: "".to_owned(), type_value: typ, visibility: From::from(&field.vis), + docs: docs_for_attrs(&field.attrs), }) } else { None @@ -304,7 +312,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { name: ast::Name, span: Span) -> Option { // The qualname for a method is the trait name or name of the struct in an impl in // which the method is declared in, followed by the method's name. - let (qualname, vis) = match self.tcx.impl_of_method(self.tcx.map.local_def_id(id)) { + let (qualname, vis, docs) = match self.tcx.impl_of_method(self.tcx.map.local_def_id(id)) { Some(impl_id) => match self.tcx.map.get_if_local(impl_id) { Some(NodeItem(item)) => { match item.node { @@ -317,7 +325,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { result.push_str(&self.tcx.item_path_str(def_id)); } result.push_str(">"); - (result, From::from(&item.vis)) + (result, From::from(&item.vis), docs_for_attrs(&item.attrs)) } _ => { span_bug!(span, @@ -339,7 +347,9 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { Some(def_id) => { match self.tcx.map.get_if_local(def_id) { Some(NodeItem(item)) => { - (format!("::{}", self.tcx.item_path_str(def_id)), From::from(&item.vis)) + (format!("::{}", self.tcx.item_path_str(def_id)), + From::from(&item.vis), + docs_for_attrs(&item.attrs)) } r => { span_bug!(span, @@ -383,6 +393,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { value: String::new(), visibility: vis, parent: Some(parent_scope), + docs: docs, }) } @@ -667,7 +678,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } fn make_signature(decl: &ast::FnDecl, generics: &ast::Generics) -> String { - let mut sig = String::new(); + let mut sig = "fn ".to_owned(); if !generics.lifetimes.is_empty() || !generics.ty_params.is_empty() { sig.push('<'); sig.push_str(&generics.lifetimes.iter() @@ -687,7 +698,7 @@ fn make_signature(decl: &ast::FnDecl, generics: &ast::Generics) -> String { sig.push_str(&decl.inputs.iter().map(arg_to_string).collect::>().join(", ")); sig.push(')'); match decl.output { - ast::FunctionRetTy::Default(_) => {} + ast::FunctionRetTy::Default(_) => sig.push_str(" -> ()"), ast::FunctionRetTy::Ty(ref t) => sig.push_str(&format!(" -> {}", ty_to_string(t))), } @@ -740,7 +751,23 @@ impl Visitor for PathCollector { } } -#[derive(Clone, Copy, Debug)] +fn docs_for_attrs(attrs: &[Attribute]) -> String { + let doc = InternedString::new("doc"); + let mut result = String::new(); + + for attr in attrs { + if attr.name() == doc { + if let Some(ref val) = attr.value_str() { + result.push_str(&strip_doc_comment_decoration(val)); + result.push('\n'); + } + } + } + + result +} + +#[derive(Clone, Copy, Debug, RustcEncodable)] pub enum Format { Csv, Json,