about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_save_analysis/data.rs11
-rw-r--r--src/librustc_save_analysis/dump_visitor.rs41
-rw-r--r--src/librustc_save_analysis/external_data.rs24
-rw-r--r--src/librustc_save_analysis/json_api_dumper.rs22
-rw-r--r--src/librustc_save_analysis/json_dumper.rs17
-rw-r--r--src/librustc_save_analysis/lib.rs43
6 files changed, 139 insertions, 19 deletions
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<NodeId>,
     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<NodeId>,
+    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<DefId>,
     pub visibility: Visibility,
+    pub docs: String,
 }
 
 /// Data for modules.
@@ -261,6 +265,7 @@ pub struct ModData {
     pub filename: String,
     pub items: Vec<NodeId>,
     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<NodeId>,
     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<NodeId>,
+    pub docs: String,
 }
 
 #[derive(Debug, RustcEncodable)]
@@ -307,6 +314,7 @@ pub struct TraitData {
     pub value: String,
     pub items: Vec<NodeId>,
     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<NodeId>,
+    pub docs: String,
 }
 
 /// Data for a typedef.
@@ -331,6 +340,7 @@ pub struct TypeDefData {
     pub value: String,
     pub visibility: Visibility,
     pub parent: Option<NodeId>,
+    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 {
                         "<mutable>".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<DefId>,
     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<DefId>,
+    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<DefId>,
     pub visibility: Visibility,
-    pub parent: Option<DefId>
+    pub parent: Option<DefId>,
+    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<DefId>,
     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<DefId>,
     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<DefId>,
+    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<DefId>,
     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<DefId>,
+    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<DefId>,
+    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<DefId>,
     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<CratePreludeData>,
     imports: Vec<Import>,
     defs: Vec<Def>,
+    // 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<Id>,
     children: Vec<Id>,
     decl_id: Option<Id>,
+    docs: String,
 }
 
 #[derive(Debug, RustcEncodable)]
@@ -209,6 +220,7 @@ impl From<EnumData> for Option<Def> {
                 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<TupleVariantData> for Option<Def> {
             parent: data.parent.map(|id| From::from(id)),
             children: vec![],
             decl_id: None,
+            docs: data.docs,
         })
     }
 }
@@ -242,6 +255,7 @@ impl From<StructVariantData> for Option<Def> {
             parent: data.parent.map(|id| From::from(id)),
             children: vec![],
             decl_id: None,
+            docs: data.docs,
         })
     }
 }
@@ -258,6 +272,7 @@ impl From<StructData> for Option<Def> {
             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<TraitData> for Option<Def> {
                 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<FunctionData> for Option<Def> {
                 children: vec![],
                 parent: data.parent.map(|id| From::from(id)),
                 decl_id: None,
+                docs: data.docs,
             }),
             _ => None,
         }
@@ -312,6 +329,7 @@ impl From<MethodData> for Option<Def> {
                 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<MacroData> for Option<Def> {
             children: vec![],
             parent: None,
             decl_id: None,
+            docs: data.docs,
         })
     }
 }
@@ -345,6 +364,7 @@ impl From<ModData> for Option<Def> {
                 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<TypeDefData> for Option<Def> {
                 children: vec![],
                 parent: data.parent.map(|id| From::from(id)),
                 decl_id: None,
+                docs: String::new(),
             }),
             _ => None,
         }
@@ -386,6 +407,7 @@ impl From<VariableData> for Option<Def> {
                 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<CratePreludeData>,
     imports: Vec<Import>,
     defs: Vec<Def>,
@@ -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<Id>,
     decl_id: Option<Id>,
+    docs: String,
 }
 
 #[derive(Debug, RustcEncodable)]
@@ -223,6 +227,7 @@ impl From<EnumData> 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<TupleVariantData> for Def {
             value: data.value,
             children: vec![],
             decl_id: None,
+            docs: data.docs,
         }
     }
 }
@@ -252,6 +258,7 @@ impl From<StructVariantData> for Def {
             value: data.value,
             children: vec![],
             decl_id: None,
+            docs: data.docs,
         }
     }
 }
@@ -266,6 +273,7 @@ impl From<StructData> 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<TraitData> 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<FunctionData> for Def {
             value: data.value,
             children: vec![],
             decl_id: None,
+            docs: data.docs,
         }
     }
 }
@@ -308,6 +318,7 @@ impl From<MethodData> 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<MacroData> for Def {
             value: String::new(),
             children: vec![],
             decl_id: None,
+            docs: data.docs,
         }
     }
 }
@@ -336,6 +348,7 @@ impl From<ModData> 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<TypeDefData> for Def {
             value: data.value,
             children: vec![],
             decl_id: None,
+            docs: String::new(),
         }
     }
 }
@@ -366,9 +380,10 @@ impl From<VariableData> 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<FunctionData> {
         // 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::<Vec<_>>().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,