From 0dbfa5f6110d96ea26f124b6dc8487e1bec3da8a Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sun, 1 Jun 2014 10:17:30 -0700 Subject: [PATCH 1/7] rustdoc: Fix some more broken links --- src/doc/index.md | 1 - src/libcore/fmt/rt.rs | 30 +++++++++++++++++++++++++++--- src/librustdoc/html/static/main.js | 5 ++++- 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/src/doc/index.md b/src/doc/index.md index 37d03d0867d..df43e0850a4 100644 --- a/src/doc/index.md +++ b/src/doc/index.md @@ -61,7 +61,6 @@ li {list-style-type: none; } * [The `time` library](time/index.html) * [The `uuid` 128-bit universally unique identifier library](uuid/index.html) * [The `url` library](url/index.html) -* [The `workcache` library](workcache/index.html) * [The `log` library](log/index.html) # Tooling diff --git a/src/libcore/fmt/rt.rs b/src/libcore/fmt/rt.rs index f2e1476cc1c..1feebbb35b6 100644 --- a/src/libcore/fmt/rt.rs +++ b/src/libcore/fmt/rt.rs @@ -14,11 +14,9 @@ //! These definitions are similar to their `ct` equivalents, but differ in that //! these can be statically allocated and are slightly optimized for the runtime -#![allow(missing_doc)] -#![doc(hidden)] - use option::Option; +#[doc(hidden)] pub enum Piece<'a> { String(&'a str), // FIXME(#8259): this shouldn't require the unit-value here @@ -26,12 +24,14 @@ pub enum Piece<'a> { Argument(Argument<'a>), } +#[doc(hidden)] pub struct Argument<'a> { pub position: Position, pub format: FormatSpec, pub method: Option<&'a Method<'a>> } +#[doc(hidden)] pub struct FormatSpec { pub fill: char, pub align: Alignment, @@ -40,38 +40,60 @@ pub struct FormatSpec { pub width: Count, } +/// Possible alignments that can be requested as part of a formatting directive. #[deriving(PartialEq)] pub enum Alignment { + /// Indication that contents should be left-aligned. AlignLeft, + /// Indication that contents should be right-aligned. AlignRight, + /// No alignment was requested. AlignUnknown, } +#[doc(hidden)] pub enum Count { CountIs(uint), CountIsParam(uint), CountIsNextParam, CountImplied, } +#[doc(hidden)] pub enum Position { ArgumentNext, ArgumentIs(uint) } +/// Flags which can be passed to formatting via a directive. +/// +/// These flags are discovered through the `flags` field of the `Formatter` +/// structure. The flag in that structure is a union of these flags into a +/// `uint` where each flag's discriminant is the corresponding bit. pub enum Flag { + /// A flag which enables number formatting to always print the sign of a + /// number. FlagSignPlus, + /// Currently not a used flag FlagSignMinus, + /// Indicates that the "alternate formatting" for a type should be used. + /// + /// The meaning of this flag is type-specific. FlagAlternate, + /// Indicates that padding should be done with a `0` character as well as + /// being aware of the sign to be printed. FlagSignAwareZeroPad, } +#[doc(hidden)] pub enum Method<'a> { Plural(Option, &'a [PluralArm<'a>], &'a [Piece<'a>]), Select(&'a [SelectArm<'a>], &'a [Piece<'a>]), } +#[doc(hidden)] pub enum PluralSelector { Keyword(PluralKeyword), Literal(uint), } +#[doc(hidden)] pub enum PluralKeyword { Zero, One, @@ -80,11 +102,13 @@ pub enum PluralKeyword { Many, } +#[doc(hidden)] pub struct PluralArm<'a> { pub selector: PluralSelector, pub result: &'a [Piece<'a>], } +#[doc(hidden)] pub struct SelectArm<'a> { pub selector: &'a str, pub result: &'a [Piece<'a>], diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 6c9bc793582..440b829c80c 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -664,7 +664,10 @@ for (var j = 0; j < structs.length; j++) { var code = $('').append(structs[j]); $.each(code.find('a'), function(idx, a) { - $(a).attr('href', rootPath + $(a).attr('href')); + var href = $(a).attr('href'); + if (!href.startsWith('http')) { + $(a).attr('href', rootPath + $(a).attr('href')); + } }); var li = $('
  • ').append(code); list.append(li); From f71f97b7c2905c7254f87a9185576939dbbb7010 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sun, 1 Jun 2014 11:06:47 -0700 Subject: [PATCH 2/7] rustdoc: Filter private methods from inlined impls Closes #14583 --- src/librustdoc/clean/inline.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 65c60f2d360..886f3c8ed7d 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -250,7 +250,12 @@ fn build_impl(tcx: &ty::ctxt, did: ast::DefId) -> clean::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 = csearch::get_impl_methods(&tcx.sess.cstore, did).iter().map(|did| { + let methods = csearch::get_impl_methods(&tcx.sess.cstore, + did).iter().filter_map(|did| { + let method = ty::method(tcx, *did); + if method.vis != ast::Public && associated_trait.is_none() { + return None + } let mut item = match ty::method(tcx, *did).clean() { clean::Provided(item) => item, clean::Required(item) => item, @@ -268,7 +273,7 @@ fn build_impl(tcx: &ty::ctxt, did: ast::DefId) -> clean::Item { } _ => fail!("not a tymethod"), }; - item + Some(item) }).collect(); clean::Item { inner: clean::ImplItem(clean::Impl { From 890754794c02615310781bc006149dddeb2770bc Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sun, 1 Jun 2014 11:09:30 -0700 Subject: [PATCH 3/7] mk: Less noisy rustdoc invocations --- mk/docs.mk | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/mk/docs.mk b/mk/docs.mk index 5a00ad6f7e8..90f85079464 100644 --- a/mk/docs.mk +++ b/mk/docs.mk @@ -110,7 +110,7 @@ HTML_DEPS += doc/version_info.html doc/version_info.html: $(D)/version_info.html.template $(MKFILE_DEPS) \ $(wildcard $(D)/*.*) | doc/ @$(call E, version-info: $@) - sed -e "s/VERSION/$(CFG_RELEASE)/; s/SHORT_HASH/$(shell echo \ + $(Q)sed -e "s/VERSION/$(CFG_RELEASE)/; s/SHORT_HASH/$(shell echo \ $(CFG_VER_HASH) | head -c 8)/;\ s/STAMP/$(CFG_VER_HASH)/;" $< >$@ @@ -156,7 +156,9 @@ doc/footer.tex: $(D)/footer.inc | doc/ # HTML (rustdoc) DOC_TARGETS += doc/not_found.html doc/not_found.html: $(D)/not_found.md $(HTML_DEPS) | doc/ - $(RUSTDOC) $(RUSTDOC_HTML_OPTS_NO_CSS) --markdown-css http://doc.rust-lang.org/rust.css $< + @$(call E, rustdoc: $@) + $(Q)$(RUSTDOC) $(RUSTDOC_HTML_OPTS_NO_CSS) \ + --markdown-css http://doc.rust-lang.org/rust.css $< define DEF_DOC @@ -164,7 +166,7 @@ define DEF_DOC DOC_TARGETS += doc/$(1).html doc/$(1).html: $$(D)/$(1).md $$(HTML_DEPS) $$(RUSTDOC_DEPS_$(1)) | doc/ @$$(call E, rustdoc: $$@) - $$(RUSTDOC) $$(RUSTDOC_HTML_OPTS) $$(RUSTDOC_FLAGS_$(1)) $$< + $$(Q)$$(RUSTDOC) $$(RUSTDOC_HTML_OPTS) $$(RUSTDOC_FLAGS_$(1)) $$< ifneq ($(ONLY_HTML_DOCS),1) From e1e8db7e4a69825720fb1ae4478b6d29b447d994 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sun, 1 Jun 2014 11:16:18 -0700 Subject: [PATCH 4/7] rustdoc: Ensure external impls are inlined once If the type associated with the impl is `pub use`'d or referenced twice in a downstream crate, the impl will attempt to be inlined twice. Closes #14584 --- src/librustdoc/clean/inline.rs | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 886f3c8ed7d..9a3a68894ab 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -207,7 +207,7 @@ fn build_impls(cx: &core::DocContext, match tcx.inherent_impls.borrow().find(&did) { None => {} Some(i) => { - impls.extend(i.borrow().iter().map(|&did| { build_impl(tcx, did) })); + impls.extend(i.borrow().iter().map(|&did| { build_impl(cx, tcx, did) })); } } @@ -223,19 +223,20 @@ fn build_impls(cx: &core::DocContext, csearch::each_top_level_item_of_crate(&tcx.sess.cstore, did.krate, |def, _, _| { - populate_impls(tcx, def, &mut impls) + populate_impls(cx, tcx, def, &mut impls) }); - fn populate_impls(tcx: &ty::ctxt, + fn populate_impls(cx: &core::DocContext, + tcx: &ty::ctxt, def: decoder::DefLike, - impls: &mut Vec) { + impls: &mut Vec>) { match def { - decoder::DlImpl(did) => impls.push(build_impl(tcx, did)), + decoder::DlImpl(did) => impls.push(build_impl(cx, tcx, did)), decoder::DlDef(ast::DefMod(did)) => { csearch::each_child_of_item(&tcx.sess.cstore, did, |def, _, _| { - populate_impls(tcx, def, impls) + populate_impls(cx, tcx, def, impls) }) } _ => {} @@ -243,10 +244,16 @@ fn build_impls(cx: &core::DocContext, } } - impls + impls.move_iter().filter_map(|a| a).collect() } -fn build_impl(tcx: &ty::ctxt, did: ast::DefId) -> clean::Item { +fn build_impl(cx: &core::DocContext, + tcx: &ty::ctxt, + did: ast::DefId) -> Option { + if !cx.inlined.borrow_mut().get_mut_ref().insert(did) { + return None + } + let associated_trait = csearch::get_impl_trait(tcx, did); let attrs = load_attrs(tcx, did); let ty = ty::lookup_item_type(tcx, did); @@ -275,7 +282,7 @@ fn build_impl(tcx: &ty::ctxt, did: ast::DefId) -> clean::Item { }; Some(item) }).collect(); - clean::Item { + Some(clean::Item { inner: clean::ImplItem(clean::Impl { derived: clean::detect_derived(attrs.as_slice()), trait_: associated_trait.clean().map(|bound| { @@ -293,7 +300,7 @@ fn build_impl(tcx: &ty::ctxt, did: ast::DefId) -> clean::Item { attrs: attrs, visibility: Some(ast::Inherited), def_id: did, - } + }) } fn build_module(cx: &core::DocContext, tcx: &ty::ctxt, From 287af7fa1a2230b25d2ffe98c5cc623ad34c6287 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sun, 1 Jun 2014 11:30:53 -0700 Subject: [PATCH 5/7] rustdoc: Deduplicate lists of implementors Inlining caused implementors to show up multiple times. cc #14584 --- src/librustdoc/html/render.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 16becde164f..2caedbc2c1c 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -108,6 +108,7 @@ pub enum ExternalLocation { /// Metadata about an implementor of a trait. pub struct Implementor { + def_id: ast::DefId, generics: clean::Generics, trait_: clean::Type, for_: clean::Type, @@ -531,6 +532,11 @@ fn write_shared(cx: &Context, try!(write!(&mut f, r"implementors['{}'] = [", krate.name)); for imp in imps.iter() { + // If the trait and implementation are in the same crate, then + // there's no need to emit information about it (there's inlining + // going on). If they're in different crates then the crate defining + // the trait will be interested in our implementation. + if imp.def_id.krate == did.krate { continue } try!(write!(&mut f, r#""impl{} {} for {}","#, imp.generics, imp.trait_, imp.for_)); } @@ -759,6 +765,7 @@ impl DocFolder for Cache { Vec::new() }); v.push(Implementor { + def_id: item.def_id, generics: i.generics.clone(), trait_: i.trait_.get_ref().clone(), for_: i.for_.clone(), From f02f739a825219a4bb5d12df2f646ea67c434a33 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 2 Jun 2014 00:09:44 -0700 Subject: [PATCH 6/7] rustdoc: Correctly inline required/provided methods Apparently relying on provided_source in ty::Method is unreliable! Closes #14594 --- src/librustdoc/clean/inline.rs | 19 ++++++++++++------- src/librustdoc/clean/mod.rs | 9 ++++----- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 9a3a68894ab..575dd057867 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -129,7 +129,7 @@ pub fn record_extern_fqn(cx: &core::DocContext, match cx.maybe_typed { core::Typed(ref tcx) => { let fqn = csearch::get_item_path(tcx, did); - let fqn = fqn.move_iter().map(|i| i.to_str().to_string()).collect(); + let fqn = fqn.move_iter().map(|i| i.to_str()).collect(); cx.external_paths.borrow_mut().get_mut_ref().insert(did, (fqn, kind)); } core::NotTyped(..) => {} @@ -138,10 +138,18 @@ pub fn record_extern_fqn(cx: &core::DocContext, pub fn build_external_trait(tcx: &ty::ctxt, did: ast::DefId) -> clean::Trait { let def = ty::lookup_trait_def(tcx, did); - let methods = ty::trait_methods(tcx, did); + let methods = ty::trait_methods(tcx, did).clean(); + let provided = ty::provided_trait_methods(tcx, did); + let mut methods = methods.move_iter().map(|meth| { + if provided.iter().any(|a| a.def_id == meth.def_id) { + clean::Provided(meth) + } else { + clean::Required(meth) + } + }); clean::Trait { generics: def.generics.clean(), - methods: methods.iter().map(|i| i.clean()).collect(), + methods: methods.collect(), parents: Vec::new(), // FIXME: this is likely wrong } } @@ -263,10 +271,7 @@ fn build_impl(cx: &core::DocContext, if method.vis != ast::Public && associated_trait.is_none() { return None } - let mut item = match ty::method(tcx, *did).clean() { - clean::Provided(item) => item, - clean::Required(item) => item, - }; + let mut item = ty::method(tcx, *did).clean(); item.inner = match item.inner.clone() { clean::TyMethodItem(clean::TyMethod { fn_style, decl, self_, generics diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 856619882c5..a289d767f95 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -942,9 +942,8 @@ impl Clean for ast::TraitMethod { } } -impl Clean for ty::Method { - fn clean(&self) -> TraitMethod { - let m = if self.provided_source.is_some() {Provided} else {Required}; +impl Clean for ty::Method { + fn clean(&self) -> Item { let cx = super::ctxtkey.get().unwrap(); let tcx = match cx.maybe_typed { core::Typed(ref tcx) => tcx, @@ -972,7 +971,7 @@ impl Clean for ty::Method { } }; - m(Item { + Item { name: Some(self.ident.clean()), visibility: Some(ast::Inherited), def_id: self.def_id, @@ -984,7 +983,7 @@ impl Clean for ty::Method { self_: self_, decl: (self.def_id, &sig).clean(), }) - }) + } } } From 1827241840656ffe7adcfb83a0f29c8deda759bd Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 3 Jun 2014 17:55:30 -0700 Subject: [PATCH 7/7] rustdoc: Put primitives in respective modules The logical location for the documentation of a primitive is in the module that declared it was a module for that primitive. --- src/librustdoc/clean/mod.rs | 28 +++++++++++++++++++--------- src/librustdoc/html/render.rs | 35 +++++++++++++++++++++-------------- 2 files changed, 40 insertions(+), 23 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index a289d767f95..1992c102e47 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -93,6 +93,7 @@ impl<'a> Clean for visit_ast::RustdocVisitor<'a> { cx.sess().cstore.iter_crate_data(|n, meta| { externs.push((n, meta.clean())); }); + externs.sort_by(|&(a, _), &(b, _)| a.cmp(&b)); // Figure out the name of this crate let input = driver::FileInput(cx.src.clone()); @@ -132,24 +133,33 @@ impl<'a> Clean for visit_ast::RustdocVisitor<'a> { _ => unreachable!(), }; let mut tmp = Vec::new(); - for child in m.items.iter() { - match child.inner { - ModuleItem(..) => {}, + for child in m.items.mut_iter() { + let inner = match child.inner { + ModuleItem(ref mut m) => m, _ => continue, - } + }; let prim = match Primitive::find(child.attrs.as_slice()) { Some(prim) => prim, None => continue, }; primitives.push(prim); - tmp.push(Item { + let mut i = Item { source: Span::empty(), name: Some(prim.to_url_str().to_string()), - attrs: child.attrs.clone(), - visibility: Some(ast::Public), + attrs: Vec::new(), + visibility: None, def_id: ast_util::local_def(prim.to_node_id()), inner: PrimitiveItem(prim), - }); + }; + // Push one copy to get indexed for the whole crate, and push a + // another copy in the proper location which will actually get + // documented. The first copy will also serve as a redirect to + // the other copy. + tmp.push(i.clone()); + i.visibility = Some(ast::Public); + i.attrs = child.attrs.clone(); + inner.items.push(i); + } m.items.extend(tmp.move_iter()); } @@ -1027,7 +1037,7 @@ pub enum Type { // region, raw, other boxes, mutable } -#[deriving(Clone, Encodable, Decodable, PartialEq, TotalEq, Hash)] +#[deriving(Clone, Encodable, Decodable, PartialEq, Eq, Hash)] pub enum Primitive { Int, I8, I16, I32, I64, Uint, U8, U16, U32, U64, diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 2caedbc2c1c..86a883bbff6 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -867,6 +867,12 @@ impl DocFolder for Cache { stack.pop(); self.paths.insert(item.def_id, (stack, item_type::Enum)); } + + clean::PrimitiveItem(..) if item.visibility.is_some() => { + self.paths.insert(item.def_id, (self.stack.clone(), + shortty(&item))); + } + _ => {} } @@ -1082,21 +1088,21 @@ impl Context { writer.flush() } + // Private modules may survive the strip-private pass if they + // contain impls for public types. These modules can also + // contain items such as publicly reexported structures. + // + // External crates will provide links to these structures, so + // these modules are recursed into, but not rendered normally (a + // flag on the context). + if !self.render_redirect_pages { + self.render_redirect_pages = ignore_private_item(&item); + } + match item.inner { // modules are special because they add a namespace. We also need to // recurse into the items of the module as well. clean::ModuleItem(..) => { - // Private modules may survive the strip-private pass if they - // contain impls for public types. These modules can also - // contain items such as publicly reexported structures. - // - // External crates will provide links to these structures, so - // these modules are recursed into, but not rendered normally (a - // flag on the context). - if !self.render_redirect_pages { - self.render_redirect_pages = ignore_private_module(&item); - } - let name = item.name.get_ref().to_string(); let mut item = Some(item); self.recurse(name, |this| { @@ -1330,7 +1336,7 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item, items: &[clean::Item]) -> fmt::Result { try!(document(w, item)); let mut indices = range(0, items.len()).filter(|i| { - !ignore_private_module(&items[*i]) + !ignore_private_item(&items[*i]) }).collect::>(); fn cmp(i1: &clean::Item, i2: &clean::Item, idx1: uint, idx2: uint) -> Ordering { @@ -2016,7 +2022,7 @@ impl<'a> fmt::Show for Sidebar<'a> { fn build_sidebar(m: &clean::Module) -> HashMap> { let mut map = HashMap::new(); for item in m.items.iter() { - if ignore_private_module(item) { continue } + if ignore_private_item(item) { continue } let short = shortty(item).to_static_str(); let myname = match item.name { @@ -2066,12 +2072,13 @@ fn item_primitive(w: &mut fmt::Formatter, render_methods(w, it) } -fn ignore_private_module(it: &clean::Item) -> bool { +fn ignore_private_item(it: &clean::Item) -> bool { match it.inner { clean::ModuleItem(ref m) => { (m.items.len() == 0 && it.doc_value().is_none()) || it.visibility != Some(ast::Public) } + clean::PrimitiveItem(..) => it.visibility != Some(ast::Public), _ => false, } }