Auto merge of #35236 - nrc:rustdoc-redirects, r=@alexcrichton
rustdoc: redirect URLs cc #35020 which does this properly r? @alexcrichton
This commit is contained in:
commit
6c0d66af69
@ -326,7 +326,7 @@ pub fn href(did: DefId) -> Option<(String, ItemType, Vec<String>)> {
|
||||
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");
|
||||
|
@ -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 {
|
||||
@ -90,7 +98,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",
|
||||
@ -113,9 +121,55 @@ 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 {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for NameSpace {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.to_static_str().fmt(f)
|
||||
}
|
||||
|
@ -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##"<!DOCTYPE html>
|
||||
</form>
|
||||
</nav>
|
||||
|
||||
<section id='main' class="content {ty}">{content}</section>
|
||||
<section id='main' class="content {css_class}">{content}</section>
|
||||
<section id='search' class="content hidden"></section>
|
||||
|
||||
<section class="footer"></section>
|
||||
@ -152,7 +152,7 @@ r##"<!DOCTYPE html>
|
||||
},
|
||||
content = *t,
|
||||
root_path = page.root_path,
|
||||
ty = page.ty,
|
||||
css_class = page.css_class,
|
||||
logo = if layout.logo.is_empty() {
|
||||
"".to_string()
|
||||
} else {
|
||||
|
@ -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;
|
||||
@ -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,6 +1283,69 @@ impl Context {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
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 {
|
||||
self.current.join("::")
|
||||
};
|
||||
if pushname {
|
||||
if !title.is_empty() {
|
||||
title.push_str("::");
|
||||
}
|
||||
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);
|
||||
|
||||
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::<String>();
|
||||
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(())
|
||||
}
|
||||
|
||||
/// 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.
|
||||
@ -1291,66 +1354,6 @@ impl Context {
|
||||
fn item<F>(&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();
|
||||
});
|
||||
|
||||
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());
|
||||
}
|
||||
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,
|
||||
};
|
||||
|
||||
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::<String>();
|
||||
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(())
|
||||
}
|
||||
|
||||
// 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,34 @@ 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),
|
||||
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(())
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn build_sidebar_items(&self, m: &clean::Module) -> BTreeMap<String, Vec<NameDoc>> {
|
||||
@ -1423,7 +1437,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 +1545,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 +1580,7 @@ impl<'a> fmt::Display for Item<'a> {
|
||||
}
|
||||
}
|
||||
write!(fmt, "<a class='{}' href=''>{}</a>",
|
||||
shortty(self.item), self.item.name.as_ref().unwrap())?;
|
||||
item_type(self.item), self.item.name.as_ref().unwrap())?;
|
||||
|
||||
write!(fmt, "</span>")?; // in-band
|
||||
write!(fmt, "<span class='out-of-band'>")?;
|
||||
@ -1622,7 +1636,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 +1728,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 +1753,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 +1839,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,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!("{}.{}", shortty(m), name));
|
||||
write!(w, "<h3 id='{id}' class='method stab {stab}'><code>",
|
||||
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, "<h3 id='{id}' class='method stab {stab}'>\
|
||||
<span id='{ns_id}' class='invisible'><code>",
|
||||
id = id,
|
||||
stab = m.stability_class())?;
|
||||
stab = m.stability_class(),
|
||||
ns_id = ns_id)?;
|
||||
render_assoc_item(w, m, AssocItemLink::Anchor(Some(&id)))?;
|
||||
write!(w, "</code>")?;
|
||||
render_stability_since(w, m, t)?;
|
||||
write!(w, "</h3>")?;
|
||||
write!(w, "</span></h3>")?;
|
||||
document(w, cx, m)?;
|
||||
Ok(())
|
||||
}
|
||||
@ -2104,7 +2122,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 +2131,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 +2209,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 +2286,19 @@ fn item_struct(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
|
||||
if fields.peek().is_some() {
|
||||
write!(w, "<h2 class='fields'>Fields</h2>")?;
|
||||
for (field, ty) in fields {
|
||||
write!(w, "<span id='{shortty}.{name}' class='{shortty}'><code>{name}: {ty}</code>
|
||||
</span><span class='stab {stab}'></span>",
|
||||
shortty = ItemType::StructField,
|
||||
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, "<span id='{id}' class='{item_type}'>
|
||||
<span id='{ns_id}' class='invisible'>
|
||||
<code>{name}: {ty}</code>
|
||||
</span></span><span class='stab {stab}'></span>",
|
||||
item_type = ItemType::StructField,
|
||||
id = id,
|
||||
ns_id = ns_id,
|
||||
stab = field.stability_class(),
|
||||
name = field.name.as_ref().unwrap(),
|
||||
ty = ty)?;
|
||||
@ -2339,8 +2367,16 @@ fn item_enum(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
|
||||
if !e.variants.is_empty() {
|
||||
write!(w, "<h2 class='variants'>Variants</h2>\n")?;
|
||||
for variant in &e.variants {
|
||||
write!(w, "<span id='{shortty}.{name}' class='variant'><code>{name}",
|
||||
shortty = ItemType::Variant,
|
||||
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, "<span id='{id}' class='variant'>\
|
||||
<span id='{ns_id}' class='invisible'><code>{name}",
|
||||
id = id,
|
||||
ns_id = ns_id,
|
||||
name = variant.name.as_ref().unwrap())?;
|
||||
if let clean::VariantItem(ref var) = variant.inner {
|
||||
if let clean::TupleVariant(ref tys) = var.kind {
|
||||
@ -2354,7 +2390,7 @@ fn item_enum(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
|
||||
write!(w, ")")?;
|
||||
}
|
||||
}
|
||||
write!(w, "</code></span>")?;
|
||||
write!(w, "</code></span></span>")?;
|
||||
document(w, cx, variant)?;
|
||||
|
||||
use clean::{Variant, StructVariant};
|
||||
@ -2364,10 +2400,20 @@ 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, "<tr><td \
|
||||
id='variant.{v}.field.{f}'>\
|
||||
<code>{f}: {t}</code></td><td>",
|
||||
v = variant.name.as_ref().unwrap(),
|
||||
id='{id}'>\
|
||||
<span id='{ns_id}' class='invisible'>\
|
||||
<code>{f}: {t}</code></span></td><td>",
|
||||
id = id,
|
||||
ns_id = ns_id,
|
||||
f = field.name.as_ref().unwrap(),
|
||||
t = *ty)?;
|
||||
document(w, cx, field)?;
|
||||
@ -2584,11 +2630,11 @@ 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 {
|
||||
let shortty = shortty(item);
|
||||
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();
|
||||
|
||||
let is_static = match item.inner {
|
||||
@ -2601,38 +2647,48 @@ 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, "<h4 id='{}' class='{}'>", id, shortty)?;
|
||||
let id = derive_id(format!("{}.{}", item_type, name));
|
||||
let ns_id = derive_id(format!("{}.{}", name, item_type.name_space()));
|
||||
write!(w, "<h4 id='{}' class='{}'>", id, item_type)?;
|
||||
write!(w, "<span id='{}' class='invisible'>", ns_id)?;
|
||||
write!(w, "<code>")?;
|
||||
render_assoc_item(w, item, link.anchor(&id))?;
|
||||
write!(w, "</code>")?;
|
||||
render_stability_since_raw(w, item.stable_since(), outer_version)?;
|
||||
write!(w, "</h4>\n")?;
|
||||
write!(w, "</span></h4>\n")?;
|
||||
}
|
||||
}
|
||||
clean::TypedefItem(ref tydef, _) => {
|
||||
let id = derive_id(format!("{}.{}", ItemType::AssociatedType, name));
|
||||
write!(w, "<h4 id='{}' class='{}'><code>", id, shortty)?;
|
||||
let ns_id = derive_id(format!("{}.{}", name, item_type.name_space()));
|
||||
write!(w, "<h4 id='{}' class='{}'>", id, item_type)?;
|
||||
write!(w, "<span id='{}' class='invisible'><code>", ns_id)?;
|
||||
assoc_type(w, item, &Vec::new(), Some(&tydef.type_), link.anchor(&id))?;
|
||||
write!(w, "</code></h4>\n")?;
|
||||
write!(w, "</code></span></h4>\n")?;
|
||||
}
|
||||
clean::AssociatedConstItem(ref ty, ref default) => {
|
||||
let id = derive_id(format!("{}.{}", shortty, name));
|
||||
write!(w, "<h4 id='{}' class='{}'><code>", id, shortty)?;
|
||||
let id = derive_id(format!("{}.{}", item_type, name));
|
||||
let ns_id = derive_id(format!("{}.{}", name, item_type.name_space()));
|
||||
write!(w, "<h4 id='{}' class='{}'>", id, item_type)?;
|
||||
write!(w, "<span id='{}' class='invisible'><code>", ns_id)?;
|
||||
assoc_const(w, item, ty, default.as_ref(), link.anchor(&id))?;
|
||||
write!(w, "</code></h4>\n")?;
|
||||
write!(w, "</code></span></h4>\n")?;
|
||||
}
|
||||
clean::ConstantItem(ref c) => {
|
||||
let id = derive_id(format!("{}.{}", shortty, name));
|
||||
write!(w, "<h4 id='{}' class='{}'><code>", id, shortty)?;
|
||||
let id = derive_id(format!("{}.{}", item_type, name));
|
||||
let ns_id = derive_id(format!("{}.{}", name, item_type.name_space()));
|
||||
write!(w, "<h4 id='{}' class='{}'>", id, item_type)?;
|
||||
write!(w, "<span id='{}' class='invisible'><code>", ns_id)?;
|
||||
assoc_const(w, item, &c.type_, Some(&c.expr), link.anchor(&id))?;
|
||||
write!(w, "</code></h4>\n")?;
|
||||
write!(w, "</code></span></h4>\n")?;
|
||||
}
|
||||
clean::AssociatedTypeItem(ref bounds, ref default) => {
|
||||
let id = derive_id(format!("{}.{}", shortty, name));
|
||||
write!(w, "<h4 id='{}' class='{}'><code>", id, shortty)?;
|
||||
let id = derive_id(format!("{}.{}", item_type, name));
|
||||
let ns_id = derive_id(format!("{}.{}", name, item_type.name_space()));
|
||||
write!(w, "<h4 id='{}' class='{}'>", id, item_type)?;
|
||||
write!(w, "<span id='{}' class='invisible'><code>", ns_id)?;
|
||||
assoc_type(w, item, bounds, default.as_ref(), link.anchor(&id))?;
|
||||
write!(w, "</code></h4>\n")?;
|
||||
write!(w, "</code></span></h4>\n")?;
|
||||
}
|
||||
clean::StrippedItem(..) => return Ok(()),
|
||||
_ => panic!("can't make docs for trait item with name {:?}", item.name)
|
||||
@ -2671,8 +2727,8 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi
|
||||
|
||||
write!(w, "<div class='impl-items'>")?;
|
||||
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,
|
||||
@ -2689,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(())
|
||||
}
|
||||
@ -2749,7 +2805,7 @@ impl<'a> fmt::Display for Sidebar<'a> {
|
||||
relpath: '{path}'\
|
||||
}};</script>",
|
||||
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
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,9 @@
|
||||
// @has assoc_types/trait.Index.html
|
||||
pub trait Index<I: ?Sized> {
|
||||
// @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;
|
||||
|
@ -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()'
|
||||
|
@ -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};
|
||||
|
@ -19,14 +19,17 @@ pub trait Bar {
|
||||
|
||||
impl Foo<u8> {
|
||||
// @has - '//*[@id="method.pass"]//code' 'fn pass()'
|
||||
// @has - '//*[@id="pass.v"]//code' 'fn pass()'
|
||||
pub fn pass() {}
|
||||
}
|
||||
impl Foo<u16> {
|
||||
// @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<u32> {
|
||||
// @has - '//*[@id="method.pass-2"]//code' 'fn pass() -> isize'
|
||||
// @has - '//*[@id="pass.v-2"]//code' 'fn pass() -> isize'
|
||||
pub fn pass() -> isize { 42 }
|
||||
}
|
||||
|
||||
|
@ -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) { } }
|
||||
|
||||
|
@ -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 {
|
||||
|
Loading…
x
Reference in New Issue
Block a user