From 7a7cd644cbcf8f57a156a32c7e1312de86682b0d Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 3 Aug 2016 13:14:59 +1200 Subject: [PATCH 1/4] rustdoc: refactoring and tidying up pulled out of #35020 --- src/librustdoc/html/format.rs | 2 +- src/librustdoc/html/item_type.rs | 4 +- src/librustdoc/html/layout.rs | 6 +- src/librustdoc/html/render.rs | 214 ++++++++++++++++--------------- 4 files changed, 114 insertions(+), 112 deletions(-) diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 854ca57e8556c..8802bc6dc42e0 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -326,7 +326,7 @@ pub fn href(did: DefId) -> Option<(String, ItemType, Vec)> { url.push_str("/index.html"); } _ => { - url.push_str(shortty.to_static_str()); + url.push_str(shortty.css_class()); url.push_str("."); url.push_str(fqp.last().unwrap()); url.push_str(".html"); diff --git a/src/librustdoc/html/item_type.rs b/src/librustdoc/html/item_type.rs index 74f7b099044f1..c3d38637ab70c 100644 --- a/src/librustdoc/html/item_type.rs +++ b/src/librustdoc/html/item_type.rs @@ -90,7 +90,7 @@ impl ItemType { } } - pub fn to_static_str(&self) -> &'static str { + pub fn css_class(&self) -> &'static str { match *self { ItemType::Module => "mod", ItemType::ExternCrate => "externcrate", @@ -117,6 +117,6 @@ impl ItemType { impl fmt::Display for ItemType { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.to_static_str().fmt(f) + self.css_class().fmt(f) } } diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index 265ed6be1552d..151e138efefbf 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -24,7 +24,7 @@ pub struct Layout { pub struct Page<'a> { pub title: &'a str, - pub ty: &'a str, + pub css_class: &'a str, pub root_path: &'a str, pub description: &'a str, pub keywords: &'a str, @@ -80,7 +80,7 @@ r##" -
{content}
+
{content}
@@ -152,7 +152,7 @@ r##" }, content = *t, root_path = page.root_path, - ty = page.ty, + css_class = page.css_class, logo = if layout.logo.is_empty() { "".to_string() } else { diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index e4e886c853347..963ea48d63420 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -587,7 +587,7 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { for &(did, ref item) in orphan_methods { if let Some(&(ref fqp, _)) = paths.get(&did) { search_index.push(IndexItem { - ty: shortty(item), + ty: item_type(item), name: item.name.clone().unwrap(), path: fqp[..fqp.len() - 1].join("::"), desc: Escape(&shorter(item.doc_value())).to_string(), @@ -714,10 +714,10 @@ fn write_shared(cx: &Context, for line in BufReader::new(File::open(path)?).lines() { let line = line?; if !line.starts_with(key) { - continue + continue; } if line.starts_with(&format!(r#"{}["{}"]"#, key, krate)) { - continue + continue; } ret.push(line.to_string()); } @@ -761,7 +761,7 @@ fn write_shared(cx: &Context, try_err!(mkdir(&mydst), &mydst); } mydst.push(&format!("{}.{}.js", - remote_item_type.to_static_str(), + remote_item_type.css_class(), remote_path[remote_path.len() - 1])); let all_implementors = try_err!(collect(&mydst, &krate.name, "implementors"), @@ -832,7 +832,7 @@ fn mkdir(path: &Path) -> io::Result<()> { } /// Returns a documentation-level item type from the item. -fn shortty(item: &clean::Item) -> ItemType { +fn item_type(item: &clean::Item) -> ItemType { ItemType::from_item(item) } @@ -952,7 +952,7 @@ impl<'a> SourceCollector<'a> { let mut fname = p.file_name().expect("source has no filename") .to_os_string(); fname.push(".html"); - cur.push(&fname[..]); + cur.push(&fname); href.push_str(&fname.to_string_lossy()); let mut w = BufWriter::new(File::create(&cur)?); @@ -961,7 +961,7 @@ impl<'a> SourceCollector<'a> { let desc = format!("Source to the Rust file `{}`.", filename); let page = layout::Page { title: &title, - ty: "source", + css_class: "source", root_path: &root_path, description: &desc, keywords: BASIC_KEYWORDS, @@ -1080,7 +1080,7 @@ impl DocFolder for Cache { // inserted later on when serializing the search-index. if item.def_id.index != CRATE_DEF_INDEX { self.search_index.push(IndexItem { - ty: shortty(&item), + ty: item_type(&item), name: s.to_string(), path: path.join("::").to_string(), desc: Escape(&shorter(item.doc_value())).to_string(), @@ -1126,7 +1126,7 @@ impl DocFolder for Cache { self.access_levels.is_public(item.def_id) { self.paths.insert(item.def_id, - (self.stack.clone(), shortty(&item))); + (self.stack.clone(), item_type(&item))); } } // link variants to their parent enum because pages aren't emitted @@ -1139,7 +1139,7 @@ impl DocFolder for Cache { clean::PrimitiveItem(..) if item.visibility.is_some() => { self.paths.insert(item.def_id, (self.stack.clone(), - shortty(&item))); + item_type(&item))); } _ => {} @@ -1283,74 +1283,77 @@ impl Context { Ok(()) } - /// Non-parallelized version of rendering an item. This will take the input - /// item, render its contents, and then invoke the specified closure with - /// all sub-items which need to be rendered. - /// - /// The rendering driver uses this closure to queue up more work. - fn item(&mut self, item: clean::Item, mut f: F) -> Result<(), Error> where - F: FnMut(&mut Context, clean::Item), - { - fn render(writer: &mut io::Write, cx: &Context, it: &clean::Item, - pushname: bool) -> io::Result<()> { - // A little unfortunate that this is done like this, but it sure - // does make formatting *a lot* nicer. - CURRENT_LOCATION_KEY.with(|slot| { - *slot.borrow_mut() = cx.current.clone(); - }); + fn render_item(&self, + writer: &mut io::Write, + it: &clean::Item, + pushname: bool) + -> io::Result<()> { + // A little unfortunate that this is done like this, but it sure + // does make formatting *a lot* nicer. + CURRENT_LOCATION_KEY.with(|slot| { + *slot.borrow_mut() = self.current.clone(); + }); - let mut title = if it.is_primitive() { - // No need to include the namespace for primitive types - String::new() - } else { - cx.current.join("::") - }; - if pushname { - if !title.is_empty() { - title.push_str("::"); - } - title.push_str(it.name.as_ref().unwrap()); + let mut title = if it.is_primitive() { + // No need to include the namespace for primitive types + String::new() + } else { + self.current.join("::") + }; + if pushname { + if !title.is_empty() { + title.push_str("::"); } - title.push_str(" - Rust"); - let tyname = shortty(it).to_static_str(); - let desc = if it.is_crate() { - format!("API documentation for the Rust `{}` crate.", - cx.shared.layout.krate) - } else { - format!("API documentation for the Rust `{}` {} in crate `{}`.", - it.name.as_ref().unwrap(), tyname, cx.shared.layout.krate) - }; - let keywords = make_item_keywords(it); - let page = layout::Page { - ty: tyname, - root_path: &cx.root_path, - title: &title, - description: &desc, - keywords: &keywords, - }; + title.push_str(it.name.as_ref().unwrap()); + } + title.push_str(" - Rust"); + let tyname = item_type(it).css_class(); + let desc = if it.is_crate() { + format!("API documentation for the Rust `{}` crate.", + self.shared.layout.krate) + } else { + format!("API documentation for the Rust `{}` {} in crate `{}`.", + it.name.as_ref().unwrap(), tyname, self.shared.layout.krate) + }; + let keywords = make_item_keywords(it); + let page = layout::Page { + css_class: tyname, + root_path: &self.root_path, + title: &title, + description: &desc, + keywords: &keywords, + }; - reset_ids(true); + reset_ids(true); - if !cx.render_redirect_pages { - layout::render(writer, &cx.shared.layout, &page, - &Sidebar{ cx: cx, item: it }, - &Item{ cx: cx, item: it }, - cx.shared.css_file_extension.is_some())?; - } else { - let mut url = repeat("../").take(cx.current.len()) - .collect::(); - if let Some(&(ref names, ty)) = cache().paths.get(&it.def_id) { - for name in &names[..names.len() - 1] { - url.push_str(name); - url.push_str("/"); - } - url.push_str(&item_path(ty, names.last().unwrap())); - layout::redirect(writer, &url)?; + if !self.render_redirect_pages { + layout::render(writer, &self.shared.layout, &page, + &Sidebar{ cx: self, item: it }, + &Item{ cx: self, item: it }, + self.shared.css_file_extension.is_some())?; + } else { + let mut url = repeat("../").take(self.current.len()) + .collect::(); + if let Some(&(ref names, ty)) = cache().paths.get(&it.def_id) { + for name in &names[..names.len() - 1] { + url.push_str(name); + url.push_str("/"); } + url.push_str(&item_path(ty, names.last().unwrap())); + layout::redirect(writer, &url)?; } - Ok(()) } + Ok(()) + } + /// Non-parallelized version of rendering an item. This will take the input + /// item, render its contents, and then invoke the specified closure with + /// all sub-items which need to be rendered. + /// + /// The rendering driver uses this closure to queue up more work. + fn item(&mut self, item: clean::Item, mut f: F) -> Result<(), Error> where + F: FnMut(&mut Context, clean::Item), + { // Stripped modules survive the rustdoc passes (i.e. `strip-private`) // if they contain impls for public types. These modules can also // contain items such as publicly reexported structures. @@ -1371,7 +1374,7 @@ impl Context { let item = item.take().unwrap(); let mut buf = Vec::new(); - render(&mut buf, this, &item, false).unwrap(); + this.render_item(&mut buf, &item, false).unwrap(); // buf will be empty if the module is stripped and there is no redirect for it if !buf.is_empty() { let joint_dst = this.dst.join("index.html"); @@ -1386,7 +1389,7 @@ impl Context { _ => unreachable!() }; - // render sidebar-items.js used throughout this module + // Render sidebar-items.js used throughout this module. if !this.render_redirect_pages { let items = this.build_sidebar_items(&m); let js_dst = this.dst.join("sidebar-items.js"); @@ -1398,23 +1401,22 @@ impl Context { for item in m.items { f(this,item); } + Ok(()) - }) + })?; } else if item.name.is_some() { let mut buf = Vec::new(); - render(&mut buf, self, &item, true).unwrap(); + self.render_item(&mut buf, &item, true).unwrap(); // buf will be empty if the item is stripped and there is no redirect for it if !buf.is_empty() { - let joint_dst = self.dst.join(&item_path(shortty(&item), + let joint_dst = self.dst.join(&item_path(item_type(&item), item.name.as_ref().unwrap())); try_err!(fs::create_dir_all(&self.dst), &self.dst); let mut dst = try_err!(File::create(&joint_dst), &joint_dst); try_err!(dst.write_all(&buf), &joint_dst); } - Ok(()) - } else { - Ok(()) } + Ok(()) } fn build_sidebar_items(&self, m: &clean::Module) -> BTreeMap> { @@ -1423,7 +1425,7 @@ impl Context { for item in &m.items { if self.maybe_ignore_item(item) { continue } - let short = shortty(item).to_static_str(); + let short = item_type(item).css_class(); let myname = match item.name { None => continue, Some(ref s) => s.to_string(), @@ -1531,7 +1533,7 @@ impl<'a> Item<'a> { } Some(format!("{path}{file}?gotosrc={goto}", path = path, - file = item_path(shortty(self.item), external_path.last().unwrap()), + file = item_path(item_type(self.item), external_path.last().unwrap()), goto = self.item.def_id.index.as_usize())) } } @@ -1566,7 +1568,7 @@ impl<'a> fmt::Display for Item<'a> { } } write!(fmt, "{}", - shortty(self.item), self.item.name.as_ref().unwrap())?; + item_type(self.item), self.item.name.as_ref().unwrap())?; write!(fmt, "")?; // in-band write!(fmt, "")?; @@ -1622,7 +1624,7 @@ impl<'a> fmt::Display for Item<'a> { fn item_path(ty: ItemType, name: &str) -> String { match ty { ItemType::Module => format!("{}/index.html", name), - _ => format!("{}.{}.html", ty.to_static_str(), name), + _ => format!("{}.{}.html", ty.css_class(), name), } } @@ -1714,8 +1716,8 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context, } fn cmp(i1: &clean::Item, i2: &clean::Item, idx1: usize, idx2: usize) -> Ordering { - let ty1 = shortty(i1); - let ty2 = shortty(i2); + let ty1 = item_type(i1); + let ty2 = item_type(i2); if ty1 != ty2 { return (reorder(ty1), idx1).cmp(&(reorder(ty2), idx2)) } @@ -1739,7 +1741,7 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context, continue; } - let myty = Some(shortty(myitem)); + let myty = Some(item_type(myitem)); if curty == Some(ItemType::ExternCrate) && myty == Some(ItemType::Import) { // Put `extern crate` and `use` re-exports in the same section. curty = myty; @@ -1825,9 +1827,9 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context, name = *myitem.name.as_ref().unwrap(), stab_docs = stab_docs, docs = shorter(Some(&Markdown(doc_value).to_string())), - class = shortty(myitem), + class = item_type(myitem), stab = myitem.stability_class(), - href = item_path(shortty(myitem), myitem.name.as_ref().unwrap()), + href = item_path(item_type(myitem), myitem.name.as_ref().unwrap()), title = full_path(cx, myitem))?; } } @@ -2022,7 +2024,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, fn trait_item(w: &mut fmt::Formatter, cx: &Context, m: &clean::Item, t: &clean::Item) -> fmt::Result { let name = m.name.as_ref().unwrap(); - let id = derive_id(format!("{}.{}", shortty(m), name)); + let id = derive_id(format!("{}.{}", item_type(m), name)); write!(w, "

", id = id, stab = m.stability_class())?; @@ -2104,7 +2106,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, let (ref path, _) = cache.external_paths[&it.def_id]; path[..path.len() - 1].join("/") }, - ty = shortty(it).to_static_str(), + ty = item_type(it).css_class(), name = *it.name.as_ref().unwrap())?; Ok(()) } @@ -2113,7 +2115,7 @@ fn naive_assoc_href(it: &clean::Item, link: AssocItemLink) -> String { use html::item_type::ItemType::*; let name = it.name.as_ref().unwrap(); - let ty = match shortty(it) { + let ty = match item_type(it) { Typedef | AssociatedType => AssociatedType, s@_ => s, }; @@ -2191,7 +2193,7 @@ fn render_assoc_item(w: &mut fmt::Formatter, link: AssocItemLink) -> fmt::Result { let name = meth.name.as_ref().unwrap(); - let anchor = format!("#{}.{}", shortty(meth), name); + let anchor = format!("#{}.{}", item_type(meth), name); let href = match link { AssocItemLink::Anchor(Some(ref id)) => format!("#{}", id), AssocItemLink::Anchor(None) => anchor, @@ -2268,9 +2270,9 @@ fn item_struct(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, if fields.peek().is_some() { write!(w, "

Fields

")?; for (field, ty) in fields { - write!(w, "{name}: {ty} + write!(w, "{name}: {ty} ", - shortty = ItemType::StructField, + item_type = ItemType::StructField, stab = field.stability_class(), name = field.name.as_ref().unwrap(), ty = ty)?; @@ -2339,8 +2341,8 @@ fn item_enum(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, if !e.variants.is_empty() { write!(w, "

Variants

\n")?; for variant in &e.variants { - write!(w, "{name}", - shortty = ItemType::Variant, + write!(w, "{name}", + item_type = ItemType::Variant, name = variant.name.as_ref().unwrap())?; if let clean::VariantItem(ref var) = variant.inner { if let clean::TupleVariant(ref tys) = var.kind { @@ -2588,7 +2590,7 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi link: AssocItemLink, render_static: bool, is_default_item: bool, outer_version: Option<&str>, trait_: Option<&clean::Trait>) -> fmt::Result { - let shortty = shortty(item); + let item_type = item_type(item); let name = item.name.as_ref().unwrap(); let is_static = match item.inner { @@ -2601,8 +2603,8 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi clean::MethodItem(..) | clean::TyMethodItem(..) => { // Only render when the method is not static or we allow static methods if !is_static || render_static { - let id = derive_id(format!("{}.{}", shortty, name)); - write!(w, "

", id, shortty)?; + let id = derive_id(format!("{}.{}", item_type, name)); + write!(w, "

", id, item_type)?; write!(w, "")?; render_assoc_item(w, item, link.anchor(&id))?; write!(w, "")?; @@ -2612,25 +2614,25 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi } clean::TypedefItem(ref tydef, _) => { let id = derive_id(format!("{}.{}", ItemType::AssociatedType, name)); - write!(w, "

", id, shortty)?; + write!(w, "

", id, item_type)?; assoc_type(w, item, &Vec::new(), Some(&tydef.type_), link.anchor(&id))?; write!(w, "

\n")?; } clean::AssociatedConstItem(ref ty, ref default) => { - let id = derive_id(format!("{}.{}", shortty, name)); - write!(w, "

", id, shortty)?; + let id = derive_id(format!("{}.{}", item_type, name)); + write!(w, "

", id, item_type)?; assoc_const(w, item, ty, default.as_ref(), link.anchor(&id))?; write!(w, "

\n")?; } clean::ConstantItem(ref c) => { - let id = derive_id(format!("{}.{}", shortty, name)); - write!(w, "

", id, shortty)?; + let id = derive_id(format!("{}.{}", item_type, name)); + write!(w, "

", id, item_type)?; assoc_const(w, item, &c.type_, Some(&c.expr), link.anchor(&id))?; write!(w, "

\n")?; } clean::AssociatedTypeItem(ref bounds, ref default) => { - let id = derive_id(format!("{}.{}", shortty, name)); - write!(w, "

", id, shortty)?; + let id = derive_id(format!("{}.{}", item_type, name)); + write!(w, "

", id, item_type)?; assoc_type(w, item, bounds, default.as_ref(), link.anchor(&id))?; write!(w, "

\n")?; } @@ -2749,7 +2751,7 @@ impl<'a> fmt::Display for Sidebar<'a> { relpath: '{path}'\ }};", name = it.name.as_ref().map(|x| &x[..]).unwrap_or(""), - ty = shortty(it).to_static_str(), + ty = item_type(it).css_class(), path = relpath)?; if parentlen == 0 { // there is no sidebar-items.js beyond the crate root path From a41454bf651a8629ec4b08365eae65b095504cab Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 3 Aug 2016 13:19:06 +1200 Subject: [PATCH 2/4] rustdoc: add namespaces for items --- src/librustdoc/html/item_type.rs | 48 ++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/src/librustdoc/html/item_type.rs b/src/librustdoc/html/item_type.rs index c3d38637ab70c..039f385d7c564 100644 --- a/src/librustdoc/html/item_type.rs +++ b/src/librustdoc/html/item_type.rs @@ -42,6 +42,14 @@ pub enum ItemType { AssociatedConst = 18, } + +#[derive(Copy, Eq, PartialEq, Clone)] +pub enum NameSpace { + Type, + Value, + Macro, +} + impl ItemType { pub fn from_item(item: &clean::Item) -> ItemType { let inner = match item.inner { @@ -113,6 +121,32 @@ impl ItemType { ItemType::AssociatedConst => "associatedconstant", } } + + pub fn name_space(&self) -> NameSpace { + match *self { + ItemType::Struct | + ItemType::Enum | + ItemType::Module | + ItemType::Typedef | + ItemType::Trait | + ItemType::Primitive | + ItemType::AssociatedType => NameSpace::Type, + + ItemType::ExternCrate | + ItemType::Import | + ItemType::Function | + ItemType::Static | + ItemType::Impl | + ItemType::TyMethod | + ItemType::Method | + ItemType::StructField | + ItemType::Variant | + ItemType::Constant | + ItemType::AssociatedConst => NameSpace::Value, + + ItemType::Macro => NameSpace::Macro, + } + } } impl fmt::Display for ItemType { @@ -120,3 +154,17 @@ impl fmt::Display for ItemType { self.css_class().fmt(f) } } + +pub const NAMESPACE_TYPE: &'static str = "t"; +pub const NAMESPACE_VALUE: &'static str = "v"; +pub const NAMESPACE_MACRO: &'static str = "m"; + +impl NameSpace { + pub fn to_static_str(&self) -> &'static str { + match *self { + NameSpace::Type => NAMESPACE_TYPE, + NameSpace::Value => NAMESPACE_VALUE, + NameSpace::Macro => NAMESPACE_MACRO, + } + } +} From 77ca7dd1073a945afcc451bee79f36cd40100996 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 3 Aug 2016 13:56:18 +1200 Subject: [PATCH 3/4] rustdoc: redirects from sane, namespaced URLs to Rustdoc's ridiculous ones cc #35020 which does this properly --- src/librustdoc/html/item_type.rs | 6 ++++ src/librustdoc/html/render.rs | 59 +++++++++++++++++++++++--------- 2 files changed, 48 insertions(+), 17 deletions(-) diff --git a/src/librustdoc/html/item_type.rs b/src/librustdoc/html/item_type.rs index 039f385d7c564..6b462a76f04ed 100644 --- a/src/librustdoc/html/item_type.rs +++ b/src/librustdoc/html/item_type.rs @@ -168,3 +168,9 @@ impl NameSpace { } } } + +impl fmt::Display for NameSpace { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.to_static_str().fmt(f) + } +} diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 963ea48d63420..51068d5648e4d 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -41,7 +41,7 @@ use std::collections::{BTreeMap, HashMap, HashSet}; use std::default::Default; use std::error; use std::fmt::{self, Display, Formatter}; -use std::fs::{self, File}; +use std::fs::{self, File, OpenOptions}; use std::io::prelude::*; use std::io::{self, BufWriter, BufReader}; use std::iter::repeat; @@ -1409,11 +1409,23 @@ impl Context { self.render_item(&mut buf, &item, true).unwrap(); // buf will be empty if the item is stripped and there is no redirect for it if !buf.is_empty() { - let joint_dst = self.dst.join(&item_path(item_type(&item), - item.name.as_ref().unwrap())); + let name = item.name.as_ref().unwrap(); + let item_type = item_type(&item); + let file_name = &item_path(item_type, name); + let joint_dst = self.dst.join(file_name); try_err!(fs::create_dir_all(&self.dst), &self.dst); let mut dst = try_err!(File::create(&joint_dst), &joint_dst); try_err!(dst.write_all(&buf), &joint_dst); + + // Redirect from a sane URL using the namespace to Rustdoc's + // URL for the page. + let redir_name = format!("{}.{}.html", name, item_type.name_space()); + let redir_dst = self.dst.join(redir_name); + if let Ok(mut redirect_out) = OpenOptions::new().create_new(true) + .write(true) + .open(&redir_dst) { + try_err!(layout::redirect(&mut redirect_out, file_name), &redir_dst); + } } } Ok(()) @@ -2270,9 +2282,12 @@ fn item_struct(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, if fields.peek().is_some() { write!(w, "

Fields

")?; for (field, ty) in fields { - write!(w, "{name}: {ty} - ", + write!(w, " + + {name}: {ty} + ", item_type = ItemType::StructField, + name_space = ItemType::StructField.name_space(), stab = field.stability_class(), name = field.name.as_ref().unwrap(), ty = ty)?; @@ -2341,8 +2356,10 @@ fn item_enum(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, if !e.variants.is_empty() { write!(w, "

Variants

\n")?; for variant in &e.variants { - write!(w, "{name}", + write!(w, "\ + {name}", item_type = ItemType::Variant, + name_space = ItemType::Variant.name_space(), name = variant.name.as_ref().unwrap())?; if let clean::VariantItem(ref var) = variant.inner { if let clean::TupleVariant(ref tys) = var.kind { @@ -2356,7 +2373,7 @@ fn item_enum(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, write!(w, ")")?; } } - write!(w, "")?; + write!(w, "")?; document(w, cx, variant)?; use clean::{Variant, StructVariant}; @@ -2368,9 +2385,12 @@ fn item_enum(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, if let StructFieldItem(ref ty) = field.inner { write!(w, "\ - {f}: {t}", + \ + {f}: {t}", v = variant.name.as_ref().unwrap(), f = field.name.as_ref().unwrap(), + vns = ItemType::Variant.name_space(), + fns = ItemType::StructField.name_space(), t = *ty)?; document(w, cx, field)?; write!(w, "")?; @@ -2605,36 +2625,41 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi if !is_static || render_static { let id = derive_id(format!("{}.{}", item_type, name)); write!(w, "

", id, item_type)?; + write!(w, "", name, item_type.name_space())?; write!(w, "")?; render_assoc_item(w, item, link.anchor(&id))?; write!(w, "")?; render_stability_since_raw(w, item.stable_since(), outer_version)?; - write!(w, "

\n")?; + write!(w, "

\n")?; } } clean::TypedefItem(ref tydef, _) => { let id = derive_id(format!("{}.{}", ItemType::AssociatedType, name)); - write!(w, "

", id, item_type)?; + write!(w, "

", id, item_type)?; + write!(w, "", name, item_type.name_space())?; assoc_type(w, item, &Vec::new(), Some(&tydef.type_), link.anchor(&id))?; - write!(w, "

\n")?; + write!(w, "

\n")?; } clean::AssociatedConstItem(ref ty, ref default) => { let id = derive_id(format!("{}.{}", item_type, name)); - write!(w, "

", id, item_type)?; + write!(w, "

", id, item_type)?; + write!(w, "", name, item_type.name_space())?; assoc_const(w, item, ty, default.as_ref(), link.anchor(&id))?; - write!(w, "

\n")?; + write!(w, "

\n")?; } clean::ConstantItem(ref c) => { let id = derive_id(format!("{}.{}", item_type, name)); - write!(w, "

", id, item_type)?; + write!(w, "

", id, item_type)?; + write!(w, "", name, item_type.name_space())?; assoc_const(w, item, &c.type_, Some(&c.expr), link.anchor(&id))?; - write!(w, "

\n")?; + write!(w, "

\n")?; } clean::AssociatedTypeItem(ref bounds, ref default) => { let id = derive_id(format!("{}.{}", item_type, name)); - write!(w, "

", id, item_type)?; + write!(w, "

", id, item_type)?; + write!(w, "", name, item_type.name_space())?; assoc_type(w, item, bounds, default.as_ref(), link.anchor(&id))?; - write!(w, "

\n")?; + write!(w, "

\n")?; } clean::StrippedItem(..) => return Ok(()), _ => panic!("can't make docs for trait item with name {:?}", item.name) From 879637f7b000c34f1c2aa6aa48d7c5bedcb55e0b Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 16 Aug 2016 10:27:07 +1200 Subject: [PATCH 4/4] Review changes --- src/librustdoc/html/render.rs | 103 +++++++++++++-------- src/librustdoc/html/static/rustdoc.css | 9 +- src/librustdoc/html/static/styles/main.css | 2 +- src/test/rustdoc/assoc-types.rs | 2 + src/test/rustdoc/issue-19190.rs | 3 + src/test/rustdoc/issue-21092.rs | 1 + src/test/rustdoc/issue-25001.rs | 3 + src/test/rustdoc/src-links.rs | 2 + src/test/rustdoc/structfields.rs | 6 ++ 9 files changed, 92 insertions(+), 39 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 51068d5648e4d..d654429146d83 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -2036,14 +2036,18 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, fn trait_item(w: &mut fmt::Formatter, cx: &Context, m: &clean::Item, t: &clean::Item) -> fmt::Result { let name = m.name.as_ref().unwrap(); - let id = derive_id(format!("{}.{}", item_type(m), name)); - write!(w, "

", + let item_type = item_type(m); + let id = derive_id(format!("{}.{}", item_type, name)); + let ns_id = derive_id(format!("{}.{}", name, item_type.name_space())); + write!(w, "

\ +

")?; + write!(w, "

")?; document(w, cx, m)?; Ok(()) } @@ -2282,12 +2286,19 @@ fn item_struct(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, if fields.peek().is_some() { write!(w, "

Fields

")?; for (field, ty) in fields { - write!(w, " - + let id = derive_id(format!("{}.{}", + ItemType::StructField, + field.name.as_ref().unwrap())); + let ns_id = derive_id(format!("{}.{}", + field.name.as_ref().unwrap(), + ItemType::StructField.name_space())); + write!(w, " + ", + ", item_type = ItemType::StructField, - name_space = ItemType::StructField.name_space(), + id = id, + ns_id = ns_id, stab = field.stability_class(), name = field.name.as_ref().unwrap(), ty = ty)?; @@ -2356,10 +2367,16 @@ fn item_enum(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, if !e.variants.is_empty() { write!(w, "

Variants

\n")?; for variant in &e.variants { - write!(w, "\ - {name}", - item_type = ItemType::Variant, - name_space = ItemType::Variant.name_space(), + let id = derive_id(format!("{}.{}", + ItemType::Variant, + variant.name.as_ref().unwrap())); + let ns_id = derive_id(format!("{}.{}", + variant.name.as_ref().unwrap(), + ItemType::Variant.name_space())); + write!(w, "\ + ")?; + write!(w, "")?; document(w, cx, variant)?; use clean::{Variant, StructVariant}; @@ -2383,14 +2400,21 @@ fn item_enum(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, for field in &s.fields { use clean::StructFieldItem; if let StructFieldItem(ref ty) = field.inner { + let id = derive_id(format!("variant.{}.field.{}", + variant.name.as_ref().unwrap(), + field.name.as_ref().unwrap())); + let ns_id = derive_id(format!("{}.{}.{}.{}", + variant.name.as_ref().unwrap(), + ItemType::Variant.name_space(), + field.name.as_ref().unwrap(), + ItemType::StructField.name_space())); write!(w, "\ - \ - {f}: {t}", - v = variant.name.as_ref().unwrap(), + id='{id}'>\ + ", + id = id, + ns_id = ns_id, f = field.name.as_ref().unwrap(), - vns = ItemType::Variant.name_space(), - fns = ItemType::StructField.name_space(), t = *ty)?; document(w, cx, field)?; write!(w, "")?; @@ -2606,10 +2630,10 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi } } - fn doctraititem(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item, - link: AssocItemLink, render_static: bool, - is_default_item: bool, outer_version: Option<&str>, - trait_: Option<&clean::Trait>) -> fmt::Result { + fn doc_impl_item(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item, + link: AssocItemLink, render_static: bool, + is_default_item: bool, outer_version: Option<&str>, + trait_: Option<&clean::Trait>) -> fmt::Result { let item_type = item_type(item); let name = item.name.as_ref().unwrap(); @@ -2624,42 +2648,47 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi // Only render when the method is not static or we allow static methods if !is_static || render_static { let id = derive_id(format!("{}.{}", item_type, name)); + let ns_id = derive_id(format!("{}.{}", name, item_type.name_space())); write!(w, "

", id, item_type)?; - write!(w, "", name, item_type.name_space())?; + write!(w, "

\n")?; + write!(w, "

\n")?; } } clean::TypedefItem(ref tydef, _) => { let id = derive_id(format!("{}.{}", ItemType::AssociatedType, name)); + let ns_id = derive_id(format!("{}.{}", name, item_type.name_space())); write!(w, "

", id, item_type)?; - write!(w, "", name, item_type.name_space())?; + write!(w, "

\n")?; + write!(w, "

\n")?; } clean::AssociatedConstItem(ref ty, ref default) => { let id = derive_id(format!("{}.{}", item_type, name)); + let ns_id = derive_id(format!("{}.{}", name, item_type.name_space())); write!(w, "

", id, item_type)?; - write!(w, "", name, item_type.name_space())?; + write!(w, "

\n")?; + write!(w, "

\n")?; } clean::ConstantItem(ref c) => { let id = derive_id(format!("{}.{}", item_type, name)); + let ns_id = derive_id(format!("{}.{}", name, item_type.name_space())); write!(w, "

", id, item_type)?; - write!(w, "", name, item_type.name_space())?; + write!(w, "

\n")?; + write!(w, "

\n")?; } clean::AssociatedTypeItem(ref bounds, ref default) => { let id = derive_id(format!("{}.{}", item_type, name)); + let ns_id = derive_id(format!("{}.{}", name, item_type.name_space())); write!(w, "

", id, item_type)?; - write!(w, "", name, item_type.name_space())?; + write!(w, "

\n")?; + write!(w, "
\n")?; } clean::StrippedItem(..) => return Ok(()), _ => panic!("can't make docs for trait item with name {:?}", item.name) @@ -2698,8 +2727,8 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi write!(w, "
")?; for trait_item in &i.inner_impl().items { - doctraititem(w, cx, trait_item, link, render_header, - false, outer_version, trait_)?; + doc_impl_item(w, cx, trait_item, link, render_header, + false, outer_version, trait_)?; } fn render_default_items(w: &mut fmt::Formatter, @@ -2716,8 +2745,8 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi let did = i.trait_.as_ref().unwrap().def_id().unwrap(); let assoc_link = AssocItemLink::GotoSource(did, &i.provided_trait_methods); - doctraititem(w, cx, trait_item, assoc_link, render_static, true, - outer_version, None)?; + doc_impl_item(w, cx, trait_item, assoc_link, render_static, true, + outer_version, None)?; } Ok(()) } diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index de0457592fc88..c97cacd10c381 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -284,7 +284,7 @@ h3.impl > .out-of-band { font-size: 21px; } -h4 > code, h3 > code { +h4 > code, h3 > code, invisible > code { position: inherit; } @@ -292,6 +292,12 @@ h4 > code, h3 > code { z-index: 5; } +.invisible { + background: rgba(0, 0, 0, 0); + width: 100%; + display: inline-block; +} + .content .in-band { margin: 0px; padding: 0px; @@ -660,6 +666,7 @@ span.since { :target > code { background: #FDFFD3; + opacity: 1; } /* Media Queries */ diff --git a/src/librustdoc/html/static/styles/main.css b/src/librustdoc/html/static/styles/main.css index aee6d15b7ca37..c64fb1b67f3d7 100644 --- a/src/librustdoc/html/static/styles/main.css +++ b/src/librustdoc/html/static/styles/main.css @@ -26,7 +26,7 @@ h1.fqn { h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), h4:not(.method):not(.type):not(.tymethod) { border-bottom-color: #DDDDDD; } -.in-band, code { +.in-band { background-color: white; } diff --git a/src/test/rustdoc/assoc-types.rs b/src/test/rustdoc/assoc-types.rs index d5047ade062dc..e5485c356c292 100644 --- a/src/test/rustdoc/assoc-types.rs +++ b/src/test/rustdoc/assoc-types.rs @@ -13,7 +13,9 @@ // @has assoc_types/trait.Index.html pub trait Index { // @has - '//*[@id="associatedtype.Output"]//code' 'type Output: ?Sized' + // @has - '//*[@id="Output.t"]//code' 'type Output: ?Sized' type Output: ?Sized; + // @has - '//*[@id="index.v"]//code' 'fn index' // @has - '//*[@id="tymethod.index"]//code' \ // "fn index<'a>(&'a self, index: I) -> &'a Self::Output" fn index<'a>(&'a self, index: I) -> &'a Self::Output; diff --git a/src/test/rustdoc/issue-19190.rs b/src/test/rustdoc/issue-19190.rs index 6289fcc6fe526..15f7528b4ba21 100644 --- a/src/test/rustdoc/issue-19190.rs +++ b/src/test/rustdoc/issue-19190.rs @@ -23,6 +23,9 @@ impl Deref for Bar { fn deref(&self) -> &Foo { loop {} } } +// @has issue_19190/Bar.t.html // @has issue_19190/struct.Bar.html +// @has - '//*[@id="foo.v"]' 'fn foo(&self)' // @has - '//*[@id="method.foo"]' 'fn foo(&self)' +// @!has - '//*[@id="static_foo.v"]' 'fn static_foo()' // @!has - '//*[@id="method.static_foo"]' 'fn static_foo()' diff --git a/src/test/rustdoc/issue-21092.rs b/src/test/rustdoc/issue-21092.rs index ff48c70fc58dc..8c5bda7584c9f 100644 --- a/src/test/rustdoc/issue-21092.rs +++ b/src/test/rustdoc/issue-21092.rs @@ -13,6 +13,7 @@ extern crate issue_21092; +// @has issue_21092/Bar.t.html // @has issue_21092/struct.Bar.html // @has - '//*[@id="associatedtype.Bar"]' 'type Bar = i32' pub use issue_21092::{Foo, Bar}; diff --git a/src/test/rustdoc/issue-25001.rs b/src/test/rustdoc/issue-25001.rs index 25c97ee2c76a9..0b6a8104661af 100644 --- a/src/test/rustdoc/issue-25001.rs +++ b/src/test/rustdoc/issue-25001.rs @@ -19,14 +19,17 @@ pub trait Bar { impl Foo { // @has - '//*[@id="method.pass"]//code' 'fn pass()' + // @has - '//*[@id="pass.v"]//code' 'fn pass()' pub fn pass() {} } impl Foo { // @has - '//*[@id="method.pass-1"]//code' 'fn pass() -> usize' + // @has - '//*[@id="pass.v-1"]//code' 'fn pass() -> usize' pub fn pass() -> usize { 42 } } impl Foo { // @has - '//*[@id="method.pass-2"]//code' 'fn pass() -> isize' + // @has - '//*[@id="pass.v-2"]//code' 'fn pass() -> isize' pub fn pass() -> isize { 42 } } diff --git a/src/test/rustdoc/src-links.rs b/src/test/rustdoc/src-links.rs index 4d7dad64b47ae..e946e2423167a 100644 --- a/src/test/rustdoc/src-links.rs +++ b/src/test/rustdoc/src-links.rs @@ -24,11 +24,13 @@ pub mod bar { // @has foo/bar/baz/index.html '//a/@href' '../../../src/foo/src-links.rs.html' pub mod baz { /// Dox + // @has foo/bar/baz/baz.v.html // @has foo/bar/baz/fn.baz.html '//a/@href' '../../../src/foo/src-links.rs.html' pub fn baz() { } } /// Dox + // @has foo/bar/Foobar.t.html // @has foo/bar/trait.Foobar.html '//a/@href' '../../src/foo/src-links.rs.html' pub trait Foobar { fn dummy(&self) { } } diff --git a/src/test/rustdoc/structfields.rs b/src/test/rustdoc/structfields.rs index c4327f70728cb..c0bfe3ffe3cf9 100644 --- a/src/test/rustdoc/structfields.rs +++ b/src/test/rustdoc/structfields.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// @has structfields/Foo.t.html +// @has - struct.Foo.html // @has structfields/struct.Foo.html pub struct Foo { // @has - //pre "pub a: ()" @@ -22,6 +24,8 @@ pub struct Foo { pub d: usize, } +// @has structfields/Bar.t.html +// @has - struct.Bar.html // @has structfields/struct.Bar.html pub struct Bar { // @has - //pre "pub a: ()" @@ -29,6 +33,8 @@ pub struct Bar { // @!has - //pre "// some fields omitted" } +// @has structfields/Qux.t.html +// @has - enum.Qux.html // @has structfields/enum.Qux.html pub enum Qux { Quz {