mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
rustdoc: Start inlining structs across crates
This commit is contained in:
parent
8b8e70ba1d
commit
c81b511bfd
@ -27,7 +27,7 @@ use rustc::metadata::csearch;
|
|||||||
use rustc::metadata::decoder;
|
use rustc::metadata::decoder;
|
||||||
use rustc::middle::ty;
|
use rustc::middle::ty;
|
||||||
|
|
||||||
use std::string::String;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use core;
|
use core;
|
||||||
use doctree;
|
use doctree;
|
||||||
@ -53,6 +53,12 @@ impl<T: Clean<U>, U> Clean<U> for @T {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: Clean<U>, U> Clean<U> for Rc<T> {
|
||||||
|
fn clean(&self) -> U {
|
||||||
|
(**self).clean()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T: Clean<U>, U> Clean<Option<U>> for Option<T> {
|
impl<T: Clean<U>, U> Clean<Option<U>> for Option<T> {
|
||||||
fn clean(&self) -> Option<U> {
|
fn clean(&self) -> Option<U> {
|
||||||
match self {
|
match self {
|
||||||
@ -337,6 +343,14 @@ impl attr::AttrMetaMethods for Attribute {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl<'a> attr::AttrMetaMethods for &'a Attribute {
|
||||||
|
fn name(&self) -> InternedString { (**self).name() }
|
||||||
|
fn value_str(&self) -> Option<InternedString> { (**self).value_str() }
|
||||||
|
fn meta_item_list<'a>(&'a self) -> Option<&'a [@ast::MetaItem]> { None }
|
||||||
|
fn name_str_pair(&self) -> Option<(InternedString, InternedString)> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[deriving(Clone, Encodable, Decodable)]
|
#[deriving(Clone, Encodable, Decodable)]
|
||||||
pub struct TyParam {
|
pub struct TyParam {
|
||||||
@ -859,10 +873,7 @@ impl Clean<TraitMethod> for ty::Method {
|
|||||||
visibility: Some(ast::Inherited),
|
visibility: Some(ast::Inherited),
|
||||||
def_id: self.def_id,
|
def_id: self.def_id,
|
||||||
attrs: load_attrs(tcx, self.def_id),
|
attrs: load_attrs(tcx, self.def_id),
|
||||||
source: Span {
|
source: Span::empty(),
|
||||||
filename: "".to_strbuf(),
|
|
||||||
loline: 0, locol: 0, hiline: 0, hicol: 0,
|
|
||||||
},
|
|
||||||
inner: TyMethodItem(TyMethod {
|
inner: TyMethodItem(TyMethod {
|
||||||
fn_style: self.fty.fn_style,
|
fn_style: self.fty.fn_style,
|
||||||
generics: self.generics.clean(),
|
generics: self.generics.clean(),
|
||||||
@ -1070,6 +1081,31 @@ 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;
|
||||||
|
let name = if self.name == unnamed_field.name {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(self.name)
|
||||||
|
};
|
||||||
|
let cx = super::ctxtkey.get().unwrap();
|
||||||
|
let tcx = match cx.maybe_typed {
|
||||||
|
core::Typed(ref tycx) => tycx,
|
||||||
|
core::NotTyped(_) => fail!(),
|
||||||
|
};
|
||||||
|
let ty = ty::lookup_item_type(tcx, self.id);
|
||||||
|
Item {
|
||||||
|
name: name.clean(),
|
||||||
|
attrs: load_attrs(tcx, self.id),
|
||||||
|
source: Span::empty(),
|
||||||
|
visibility: Some(self.vis),
|
||||||
|
def_id: self.id,
|
||||||
|
inner: StructFieldItem(TypedStructField(ty.ty.clean())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub type Visibility = ast::Visibility;
|
pub type Visibility = ast::Visibility;
|
||||||
|
|
||||||
impl Clean<Option<Visibility>> for ast::Visibility {
|
impl Clean<Option<Visibility>> for ast::Visibility {
|
||||||
@ -1199,6 +1235,16 @@ pub struct Span {
|
|||||||
pub hicol: uint,
|
pub hicol: uint,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Span {
|
||||||
|
fn empty() -> Span {
|
||||||
|
Span {
|
||||||
|
filename: "".to_strbuf(),
|
||||||
|
loline: 0, locol: 0,
|
||||||
|
hiline: 0, hicol: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Clean<Span> for syntax::codemap::Span {
|
impl Clean<Span> for syntax::codemap::Span {
|
||||||
fn clean(&self) -> Span {
|
fn clean(&self) -> Span {
|
||||||
let ctxt = super::ctxtkey.get().unwrap();
|
let ctxt = super::ctxtkey.get().unwrap();
|
||||||
@ -1270,6 +1316,12 @@ impl Clean<String> for ast::Ident {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Clean<StrBuf> for ast::Name {
|
||||||
|
fn clean(&self) -> StrBuf {
|
||||||
|
token::get_name(*self).get().to_strbuf()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[deriving(Clone, Encodable, Decodable)]
|
#[deriving(Clone, Encodable, Decodable)]
|
||||||
pub struct Typedef {
|
pub struct Typedef {
|
||||||
pub type_: Type,
|
pub type_: Type,
|
||||||
@ -1366,19 +1418,14 @@ pub struct Impl {
|
|||||||
pub derived: bool,
|
pub derived: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn detect_derived<M: AttrMetaMethods>(attrs: &[M]) -> bool {
|
||||||
|
attrs.iter().any(|attr| {
|
||||||
|
attr.name().get() == "automatically_derived"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
impl Clean<Item> for doctree::Impl {
|
impl Clean<Item> for doctree::Impl {
|
||||||
fn clean(&self) -> Item {
|
fn clean(&self) -> Item {
|
||||||
let mut derived = false;
|
|
||||||
for attr in self.attrs.iter() {
|
|
||||||
match attr.node.value.node {
|
|
||||||
ast::MetaWord(ref s) => {
|
|
||||||
if s.get() == "automatically_derived" {
|
|
||||||
derived = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Item {
|
Item {
|
||||||
name: None,
|
name: None,
|
||||||
attrs: self.attrs.clean(),
|
attrs: self.attrs.clean(),
|
||||||
@ -1390,7 +1437,7 @@ impl Clean<Item> for doctree::Impl {
|
|||||||
trait_: self.trait_.clean(),
|
trait_: self.trait_.clean(),
|
||||||
for_: self.for_.clean(),
|
for_: self.for_.clean(),
|
||||||
methods: self.methods.clean(),
|
methods: self.methods.clean(),
|
||||||
derived: derived,
|
derived: detect_derived(self.attrs.as_slice()),
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1427,7 +1474,9 @@ impl Clean<Vec<Item>> for ast::ViewItem {
|
|||||||
ast::ViewPathList(ref a, ref list, ref b) => {
|
ast::ViewPathList(ref a, ref list, ref b) => {
|
||||||
let remaining = list.iter().filter(|path| {
|
let remaining = list.iter().filter(|path| {
|
||||||
match try_inline(path.node.id) {
|
match try_inline(path.node.id) {
|
||||||
Some(item) => { ret.push(item); false }
|
Some(items) => {
|
||||||
|
ret.extend(items.move_iter()); false
|
||||||
|
}
|
||||||
None => true,
|
None => true,
|
||||||
}
|
}
|
||||||
}).map(|a| a.clone()).collect::<Vec<ast::PathListIdent>>();
|
}).map(|a| a.clone()).collect::<Vec<ast::PathListIdent>>();
|
||||||
@ -1441,7 +1490,7 @@ impl Clean<Vec<Item>> for ast::ViewItem {
|
|||||||
}
|
}
|
||||||
ast::ViewPathSimple(_, _, id) => {
|
ast::ViewPathSimple(_, _, id) => {
|
||||||
match try_inline(id) {
|
match try_inline(id) {
|
||||||
Some(item) => ret.push(item),
|
Some(items) => ret.extend(items.move_iter()),
|
||||||
None => ret.push(convert(&self.node)),
|
None => ret.push(convert(&self.node)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1453,7 +1502,7 @@ impl Clean<Vec<Item>> for ast::ViewItem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_inline(id: ast::NodeId) -> Option<Item> {
|
fn try_inline(id: ast::NodeId) -> Option<Vec<Item>> {
|
||||||
let cx = super::ctxtkey.get().unwrap();
|
let cx = super::ctxtkey.get().unwrap();
|
||||||
let tcx = match cx.maybe_typed {
|
let tcx = match cx.maybe_typed {
|
||||||
core::Typed(ref tycx) => tycx,
|
core::Typed(ref tycx) => tycx,
|
||||||
@ -1465,23 +1514,28 @@ fn try_inline(id: ast::NodeId) -> Option<Item> {
|
|||||||
};
|
};
|
||||||
let did = ast_util::def_id_of_def(def);
|
let did = ast_util::def_id_of_def(def);
|
||||||
if ast_util::is_local(did) { return None }
|
if ast_util::is_local(did) { return None }
|
||||||
|
|
||||||
|
let mut ret = Vec::new();
|
||||||
let inner = match def {
|
let inner = match def {
|
||||||
ast::DefTrait(did) => TraitItem(build_external_trait(tcx, did)),
|
ast::DefTrait(did) => TraitItem(build_external_trait(tcx, did)),
|
||||||
ast::DefFn(did, style) =>
|
ast::DefFn(did, style) =>
|
||||||
FunctionItem(build_external_function(tcx, did, style)),
|
FunctionItem(build_external_function(tcx, did, style)),
|
||||||
|
ast::DefStruct(did) => {
|
||||||
|
ret.extend(build_impls(tcx, did).move_iter());
|
||||||
|
StructItem(build_struct(tcx, did))
|
||||||
|
}
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
let fqn = csearch::get_item_path(tcx, did);
|
let fqn = csearch::get_item_path(tcx, did);
|
||||||
Some(Item {
|
ret.push(Item {
|
||||||
source: Span {
|
source: Span::empty(),
|
||||||
filename: "".to_strbuf(), loline: 0, locol: 0, hiline: 0, hicol: 0,
|
|
||||||
},
|
|
||||||
name: Some(fqn.last().unwrap().to_str().to_strbuf()),
|
name: Some(fqn.last().unwrap().to_str().to_strbuf()),
|
||||||
attrs: load_attrs(tcx, did),
|
attrs: load_attrs(tcx, did),
|
||||||
inner: inner,
|
inner: inner,
|
||||||
visibility: Some(ast::Public),
|
visibility: Some(ast::Public),
|
||||||
def_id: did,
|
def_id: did,
|
||||||
})
|
});
|
||||||
|
Some(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_attrs(tcx: &ty::ctxt, did: ast::DefId) -> Vec<Attribute> {
|
fn load_attrs(tcx: &ty::ctxt, did: ast::DefId) -> Vec<Attribute> {
|
||||||
@ -1726,7 +1780,7 @@ fn register_def(cx: &core::DocContext, def: ast::Def) -> ast::DefId {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn build_external_trait(tcx: &ty::ctxt, did: ast::DefId) -> Trait {
|
fn build_external_trait(tcx: &ty::ctxt, did: ast::DefId) -> Trait {
|
||||||
let def = csearch::get_trait_def(tcx, did);
|
let def = ty::lookup_trait_def(tcx, did);
|
||||||
let methods = ty::trait_methods(tcx, did);
|
let methods = ty::trait_methods(tcx, did);
|
||||||
Trait {
|
Trait {
|
||||||
generics: def.generics.clean(),
|
generics: def.generics.clean(),
|
||||||
@ -1738,7 +1792,7 @@ fn build_external_trait(tcx: &ty::ctxt, did: ast::DefId) -> Trait {
|
|||||||
fn build_external_function(tcx: &ty::ctxt,
|
fn build_external_function(tcx: &ty::ctxt,
|
||||||
did: ast::DefId,
|
did: ast::DefId,
|
||||||
style: ast::FnStyle) -> Function {
|
style: ast::FnStyle) -> Function {
|
||||||
let t = csearch::get_type(tcx, did);
|
let t = ty::lookup_item_type(tcx, did);
|
||||||
Function {
|
Function {
|
||||||
decl: match ty::get(t.ty).sty {
|
decl: match ty::get(t.ty).sty {
|
||||||
ty::ty_bare_fn(ref f) => f.sig.clean(),
|
ty::ty_bare_fn(ref f) => f.sig.clean(),
|
||||||
@ -1749,6 +1803,111 @@ fn build_external_function(tcx: &ty::ctxt,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn build_struct(tcx: &ty::ctxt, did: ast::DefId) -> Struct {
|
||||||
|
use syntax::parse::token::special_idents::unnamed_field;
|
||||||
|
|
||||||
|
let t = ty::lookup_item_type(tcx, did);
|
||||||
|
let fields = ty::lookup_struct_fields(tcx, did);
|
||||||
|
|
||||||
|
Struct {
|
||||||
|
struct_type: match fields.as_slice() {
|
||||||
|
[] => doctree::Unit,
|
||||||
|
[ref f] if f.name == unnamed_field.name => doctree::Newtype,
|
||||||
|
[ref f, ..] if f.name == unnamed_field.name => doctree::Tuple,
|
||||||
|
_ => doctree::Plain,
|
||||||
|
},
|
||||||
|
generics: t.generics.clean(),
|
||||||
|
fields: fields.iter().map(|f| f.clean()).collect(),
|
||||||
|
fields_stripped: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_impls(tcx: &ty::ctxt,
|
||||||
|
did: ast::DefId) -> Vec<Item> {
|
||||||
|
ty::populate_implementations_for_type_if_necessary(tcx, did);
|
||||||
|
let mut impls = Vec::new();
|
||||||
|
|
||||||
|
match tcx.inherent_impls.borrow().find(&did) {
|
||||||
|
None => {}
|
||||||
|
Some(i) => {
|
||||||
|
impls.extend(i.borrow().iter().map(|&did| { build_impl(tcx, did) }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// csearch::each_impl(&tcx.sess.cstore, did.krate, |imp| {
|
||||||
|
// // if imp.krate
|
||||||
|
// let t = ty::lookup_item_type(tcx, imp);
|
||||||
|
// println!("{}", ::rustc::util::ppaux::ty_to_str(tcx, t.ty));
|
||||||
|
// match ty::get(t.ty).sty {
|
||||||
|
// ty::ty_struct(tdid, _) |
|
||||||
|
// ty::ty_enum(tdid, _) if tdid == did => {
|
||||||
|
// impls.push(build_impl(tcx, imp));
|
||||||
|
// }
|
||||||
|
// _ => {}
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// for (k, v) in tcx.trait_impls.borrow().iter() {
|
||||||
|
// if k.krate != did.krate { continue }
|
||||||
|
// for imp in v.borrow().iter() {
|
||||||
|
// if imp.krate != did.krate { continue }
|
||||||
|
// let t = ty::lookup_item_type(tcx, *imp);
|
||||||
|
// println!("{}", ::rustc::util::ppaux::ty_to_str(tcx, t.ty));
|
||||||
|
// match ty::get(t.ty).sty {
|
||||||
|
// ty::ty_struct(tdid, _) |
|
||||||
|
// ty::ty_enum(tdid, _) if tdid == did => {
|
||||||
|
// impls.push(build_impl(tcx, *imp));
|
||||||
|
// }
|
||||||
|
// _ => {}
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
impls
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_impl(tcx: &ty::ctxt, did: ast::DefId) -> Item {
|
||||||
|
let associated_trait = csearch::get_impl_trait(tcx, did);
|
||||||
|
let attrs = load_attrs(tcx, did);
|
||||||
|
let ty = ty::lookup_item_type(tcx, did);
|
||||||
|
let methods = tcx.impl_methods.borrow().get(&did).iter().map(|did| {
|
||||||
|
let mut item = match ty::method(tcx, *did).clean() {
|
||||||
|
Provided(item) => item,
|
||||||
|
Required(item) => item,
|
||||||
|
};
|
||||||
|
item.inner = match item.inner.clone() {
|
||||||
|
TyMethodItem(TyMethod { fn_style, decl, self_, generics }) => {
|
||||||
|
MethodItem(Method {
|
||||||
|
fn_style: fn_style,
|
||||||
|
decl: decl,
|
||||||
|
self_: self_,
|
||||||
|
generics: generics,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
_ => fail!("not a tymethod"),
|
||||||
|
};
|
||||||
|
item
|
||||||
|
}).collect();
|
||||||
|
Item {
|
||||||
|
inner: ImplItem(Impl {
|
||||||
|
derived: detect_derived(attrs.as_slice()),
|
||||||
|
trait_: associated_trait.clean().map(|bound| {
|
||||||
|
match bound {
|
||||||
|
TraitBound(ty) => ty,
|
||||||
|
RegionBound => fail!(),
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
for_: ty.ty.clean(),
|
||||||
|
generics: ty.generics.clean(),
|
||||||
|
methods: methods,
|
||||||
|
}),
|
||||||
|
source: Span::empty(),
|
||||||
|
name: None,
|
||||||
|
attrs: attrs,
|
||||||
|
visibility: Some(ast::Inherited),
|
||||||
|
def_id: did,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn resolve_use_source(path: Path, id: ast::NodeId) -> ImportSource {
|
fn resolve_use_source(path: Path, id: ast::NodeId) -> ImportSource {
|
||||||
ImportSource {
|
ImportSource {
|
||||||
path: path,
|
path: path,
|
||||||
|
@ -132,7 +132,7 @@ pub struct Cache {
|
|||||||
///
|
///
|
||||||
/// The values of the map are a list of implementations and documentation
|
/// The values of the map are a list of implementations and documentation
|
||||||
/// found on that implementation.
|
/// found on that implementation.
|
||||||
pub impls: HashMap<ast::NodeId, Vec<(clean::Impl, Option<String>)>>,
|
pub impls: HashMap<ast::DefId, Vec<(clean::Impl, Option<String>)>>,
|
||||||
|
|
||||||
/// Maintains a mapping of local crate node ids to the fully qualified name
|
/// Maintains a mapping of local crate node ids to the fully qualified name
|
||||||
/// and "short type description" of that node. This is used when generating
|
/// and "short type description" of that node. This is used when generating
|
||||||
@ -837,10 +837,8 @@ impl DocFolder for Cache {
|
|||||||
match item {
|
match item {
|
||||||
clean::Item{ attrs, inner: clean::ImplItem(i), .. } => {
|
clean::Item{ attrs, inner: clean::ImplItem(i), .. } => {
|
||||||
match i.for_ {
|
match i.for_ {
|
||||||
clean::ResolvedPath { did, .. }
|
clean::ResolvedPath { did, .. } => {
|
||||||
if ast_util::is_local(did) =>
|
let v = self.impls.find_or_insert_with(did, |_| {
|
||||||
{
|
|
||||||
let v = self.impls.find_or_insert_with(did.node, |_| {
|
|
||||||
Vec::new()
|
Vec::new()
|
||||||
});
|
});
|
||||||
// extract relevant documentation for this impl
|
// extract relevant documentation for this impl
|
||||||
@ -1664,7 +1662,7 @@ fn render_struct(w: &mut fmt::Formatter, it: &clean::Item,
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn render_methods(w: &mut fmt::Formatter, it: &clean::Item) -> fmt::Result {
|
fn render_methods(w: &mut fmt::Formatter, it: &clean::Item) -> fmt::Result {
|
||||||
match cache_key.get().unwrap().impls.find(&it.def_id.node) {
|
match cache_key.get().unwrap().impls.find(&it.def_id) {
|
||||||
Some(v) => {
|
Some(v) => {
|
||||||
let mut non_trait = v.iter().filter(|p| {
|
let mut non_trait = v.iter().filter(|p| {
|
||||||
p.ref0().trait_.is_none()
|
p.ref0().trait_.is_none()
|
||||||
|
@ -152,7 +152,8 @@ impl<'a> fold::DocFolder for Stripper<'a> {
|
|||||||
clean::ImplItem(clean::Impl{
|
clean::ImplItem(clean::Impl{
|
||||||
for_: clean::ResolvedPath{ did, .. }, ..
|
for_: clean::ResolvedPath{ did, .. }, ..
|
||||||
}) => {
|
}) => {
|
||||||
if !self.exported_items.contains(&did.node) {
|
if ast_util::is_local(did) &&
|
||||||
|
!self.exported_items.contains(&did.node) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user