Skip to content

Commit

Permalink
rustdoc: show struct field docs when inlined
Browse files Browse the repository at this point in the history
Some minor changes to the compiler to expose this information. Very
inconvenient since struct fields aren't an item. Adds (yet another) table to
metadata.

Closes #15739
  • Loading branch information
emberian committed Jul 28, 2014
1 parent 79e9f14 commit 531a3c6
Show file tree
Hide file tree
Showing 8 changed files with 67 additions and 6 deletions.
4 changes: 4 additions & 0 deletions src/librustc/metadata/common.rs
Expand Up @@ -227,3 +227,7 @@ pub static tag_region_param_def_index: uint = 0x94;
pub static tag_unboxed_closures: uint = 0x95;
pub static tag_unboxed_closure: uint = 0x96;
pub static tag_unboxed_closure_type: uint = 0x97;

pub static tag_struct_fields: uint = 0x98;
pub static tag_struct_field: uint = 0x99;
pub static tag_struct_field_id: uint = 0x9a;
8 changes: 8 additions & 0 deletions src/librustc/metadata/csearch.rs
Expand Up @@ -29,6 +29,8 @@ use syntax::attr;
use syntax::diagnostic::expect;
use syntax::parse::token;

use std::collections::hashmap::HashMap;

pub struct StaticMethodInfo {
pub ident: ast::Ident,
pub def_id: ast::DefId,
Expand Down Expand Up @@ -192,6 +194,12 @@ pub fn get_struct_fields(cstore: &cstore::CStore,
decoder::get_struct_fields(cstore.intr.clone(), &*cdata, def.node)
}

pub fn get_struct_field_attrs(cstore: &cstore::CStore, def: ast::DefId) -> HashMap<ast::NodeId,
Vec<ast::Attribute>> {
let cdata = cstore.get_crate_data(def.krate);
decoder::get_struct_field_attrs(&*cdata)
}

pub fn get_type(tcx: &ty::ctxt,
def: ast::DefId)
-> ty::Polytype {
Expand Down
14 changes: 14 additions & 0 deletions src/librustc/metadata/decoder.rs
Expand Up @@ -34,6 +34,7 @@ use std::hash::Hash;
use std::hash;
use std::io::extensions::u64_from_be_bytes;
use std::io;
use std::collections::hashmap::HashMap;
use std::rc::Rc;
use std::u64;
use serialize::ebml::reader;
Expand Down Expand Up @@ -963,6 +964,19 @@ pub fn get_item_attrs(cdata: Cmd,
f(get_attributes(item));
}

pub fn get_struct_field_attrs(cdata: Cmd) -> HashMap<ast::NodeId, Vec<ast::Attribute>> {
let data = ebml::Doc::new(cdata.data());
let fields = reader::get_doc(data, tag_struct_fields);
let mut map = HashMap::new();
reader::tagged_docs(fields, tag_struct_field, |field| {
let id = reader::doc_as_u32(reader::get_doc(field, tag_struct_field_id));
let attrs = get_attributes(field);
map.insert(id, attrs);
true
});
map
}

fn struct_field_family_to_visibility(family: Family) -> ast::Visibility {
match family {
PublicField => ast::Public,
Expand Down
25 changes: 25 additions & 0 deletions src/librustc/metadata/encoder.rs
Expand Up @@ -1644,6 +1644,29 @@ fn encode_unboxed_closures<'a>(
ebml_w.end_tag();
}

fn encode_struct_field_attrs(ebml_w: &mut Encoder, krate: &Crate) {
struct StructFieldVisitor<'a, 'b> {
ebml_w: &'a mut Encoder<'b>,
}

impl<'a, 'b> Visitor<()> for StructFieldVisitor<'a, 'b> {
fn visit_struct_field(&mut self, field: &ast::StructField, _: ()) {
self.ebml_w.start_tag(tag_struct_field);
self.ebml_w.wr_tagged_u32(tag_struct_field_id, field.node.id);
encode_attributes(self.ebml_w, field.node.attrs.as_slice());
self.ebml_w.end_tag();
}
}

ebml_w.start_tag(tag_struct_fields);
visit::walk_crate(&mut StructFieldVisitor {
ebml_w: ebml_w
}, krate, ());
ebml_w.end_tag();
}



struct ImplVisitor<'a,'b,'c> {
ecx: &'a EncodeContext<'b>,
ebml_w: &'a mut Encoder<'c>,
Expand Down Expand Up @@ -1928,6 +1951,8 @@ fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, krate: &Crate)
stats.index_bytes = ebml_w.writer.tell().unwrap() - i;
ebml_w.end_tag();

encode_struct_field_attrs(&mut ebml_w, krate);

stats.total_bytes = ebml_w.writer.tell().unwrap();

if tcx.sess.meta_stats() {
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/middle/ty.rs
Expand Up @@ -4071,7 +4071,7 @@ pub fn lookup_struct_fields(cx: &ctxt, did: ast::DefId) -> Vec<field_ty> {

let len = results.as_slice().iter().map(|x| x.len()).sum();
let mut result: Vec<field_ty> = Vec::with_capacity(len);
result.extend(results.as_slice().iter().flat_map(|rs| rs.iter().map(|&f| f)));
result.extend(results.as_slice().iter().flat_map(|rs| rs.iter().map(|f| f.clone())));
assert!(result.len() == len);
result
} else {
Expand All @@ -4085,7 +4085,7 @@ pub fn lookup_struct_field(cx: &ctxt,
-> field_ty {
let r = lookup_struct_fields(cx, parent);
match r.iter().find(|f| f.id.node == field_id.node) {
Some(t) => *t,
Some(t) => t.clone(),
None => cx.sess.bug("struct ID not found in parent's fields")
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/typeck/check/_match.rs
Expand Up @@ -322,7 +322,7 @@ pub fn check_struct_pat_fields(pcx: &pat_ctxt,
}
Some(&(index, ref mut used)) => {
*used = true;
let class_field = *class_fields.get(index);
let class_field = class_fields.get(index).clone();
let field_type = ty::lookup_field_type(tcx,
class_id,
class_field.id,
Expand Down
2 changes: 1 addition & 1 deletion src/librustdoc/clean/inline.rs
Expand Up @@ -209,7 +209,7 @@ fn build_struct(tcx: &ty::ctxt, did: ast::DefId) -> clean::Struct {
_ => doctree::Plain,
},
generics: (&t.generics, subst::TypeSpace).clean(),
fields: fields.iter().map(|f| f.clean()).collect(),
fields: fields.clean(),
fields_stripped: false,
}
}
Expand Down
14 changes: 12 additions & 2 deletions src/librustdoc/clean/mod.rs
Expand Up @@ -1320,16 +1320,26 @@ impl Clean<Item> for ast::StructField {
impl Clean<Item> for ty::field_ty {
fn clean(&self) -> Item {
use syntax::parse::token::special_idents::unnamed_field;
use rustc::metadata::csearch;

let cx = get_cx();
let attrs;

let attr_map = csearch::get_struct_field_attrs(&cx.tcx().sess.cstore, self.id);

let name = if self.name == unnamed_field.name {
attrs = None;
None
} else {
attrs = Some(attr_map.find(&self.id.node).unwrap());
Some(self.name)
};
let cx = get_cx();

let ty = ty::lookup_item_type(cx.tcx(), self.id);

Item {
name: name.clean(),
attrs: inline::load_attrs(cx.tcx(), self.id),
attrs: attrs.unwrap_or(&Vec::new()).clean(),
source: Span::empty(),
visibility: Some(self.vis),
stability: get_stability(self.id),
Expand Down

0 comments on commit 531a3c6

Please sign in to comment.