From ef71c08d6af1d726b392f77498d6ee170aa0ed44 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Sat, 23 Jul 2016 17:32:32 +1200 Subject: [PATCH 1/2] rustdoc: simplify URLs Changes rustdoc URLs to name.namespace.html, e.g., Foo.t.html. These are easier for clients to guess since they only need to know the namespace, not the kind of item. Old URLs are preserved as redirects to the new ones. I also add redirects for modules, e.g., foo/bar/baz.t.html to foo/bar/baz/index.html, so modules are not an exception to the URL rule. And removes the ! from macro URLs. Closes #34271 --- src/librustdoc/clean/mod.rs | 8 +- src/librustdoc/html/format.rs | 10 +- src/librustdoc/html/item_type.rs | 51 +- src/librustdoc/html/layout.rs | 6 +- src/librustdoc/html/render.rs | 455 +++++++++++------- src/librustdoc/html/static/main.js | 78 +-- src/test/rustdoc/assoc-consts.rs | 6 +- src/test/rustdoc/assoc-types.rs | 12 +- src/test/rustdoc/cap-lints.rs | 2 +- src/test/rustdoc/deprecated-impls.rs | 6 +- src/test/rustdoc/deprecated.rs | 2 +- .../rustdoc/duplicate_impls/issue-33054.rs | 4 +- src/test/rustdoc/escape-rust-expr.rs | 2 +- src/test/rustdoc/extern-default-method.rs | 2 +- src/test/rustdoc/extern-impl.rs | 4 +- src/test/rustdoc/extern-method.rs | 12 +- src/test/rustdoc/ffi.rs | 4 +- src/test/rustdoc/hidden-impls.rs | 4 +- src/test/rustdoc/hidden-line.rs | 2 +- src/test/rustdoc/impl-parts-crosscrate.rs | 2 +- src/test/rustdoc/impl-parts.rs | 4 +- src/test/rustdoc/inline-default-methods.rs | 2 +- .../rustdoc/inline_cross/inline_hidden.rs | 2 +- src/test/rustdoc/inline_cross/issue-28480.rs | 4 +- .../rustdoc/inline_cross/issue-31948-1.rs | 10 +- .../rustdoc/inline_cross/issue-31948-2.rs | 10 +- src/test/rustdoc/inline_cross/issue-31948.rs | 14 +- src/test/rustdoc/inline_cross/issue-32881.rs | 2 +- src/test/rustdoc/inline_cross/issue-33113.rs | 2 +- src/test/rustdoc/inline_local/issue-28537.rs | 4 +- src/test/rustdoc/inline_local/issue-32343.rs | 8 +- .../rustdoc/inline_local/please_inline.rs | 4 +- src/test/rustdoc/issue-12834.rs | 2 +- src/test/rustdoc/issue-13698.rs | 4 +- src/test/rustdoc/issue-15169.rs | 2 +- src/test/rustdoc/issue-15318-2.rs | 4 +- src/test/rustdoc/issue-15318-3.rs | 2 +- src/test/rustdoc/issue-15318.rs | 4 +- src/test/rustdoc/issue-15347.rs | 2 +- src/test/rustdoc/issue-17476.rs | 4 +- src/test/rustdoc/issue-19055.rs | 10 +- src/test/rustdoc/issue-19190-2.rs | 6 +- src/test/rustdoc/issue-19190-3.rs | 18 +- src/test/rustdoc/issue-19190.rs | 6 +- src/test/rustdoc/issue-20175.rs | 4 +- src/test/rustdoc/issue-20646.rs | 12 +- src/test/rustdoc/issue-20727-2.rs | 4 +- src/test/rustdoc/issue-20727-3.rs | 4 +- src/test/rustdoc/issue-20727-4.rs | 8 +- src/test/rustdoc/issue-20727.rs | 4 +- src/test/rustdoc/issue-21092.rs | 4 +- src/test/rustdoc/issue-21474.rs | 2 +- src/test/rustdoc/issue-21801.rs | 4 +- src/test/rustdoc/issue-22038.rs | 8 +- src/test/rustdoc/issue-25001.rs | 20 +- src/test/rustdoc/issue-26606.rs | 4 +- src/test/rustdoc/issue-27759.rs | 2 +- src/test/rustdoc/issue-27862.rs | 2 +- src/test/rustdoc/issue-28478.rs | 26 +- src/test/rustdoc/issue-29449.rs | 2 +- src/test/rustdoc/issue-29503.rs | 2 +- src/test/rustdoc/issue-29584.rs | 2 +- src/test/rustdoc/issue-30109.rs | 4 +- src/test/rustdoc/issue-32374.rs | 2 +- src/test/rustdoc/issue-32395.rs | 4 +- src/test/rustdoc/issue-32890.rs | 9 +- src/test/rustdoc/issue-33069.rs | 2 +- src/test/rustdoc/issue-33302.rs | 14 +- src/test/rustdoc/issue-33592.rs | 4 +- src/test/rustdoc/issue-34274.rs | 2 +- src/test/rustdoc/issue-34928.rs | 2 +- src/test/rustdoc/macros.rs | 2 +- src/test/rustdoc/manual_impl.rs | 8 +- src/test/rustdoc/must-use.rs | 4 +- src/test/rustdoc/negative-impl.rs | 8 +- src/test/rustdoc/prim-title.rs | 2 +- src/test/rustdoc/redirect-const.rs | 8 +- src/test/rustdoc/redirect-rename.rs | 12 +- src/test/rustdoc/redirect.rs | 12 +- src/test/rustdoc/smoke.rs | 8 +- src/test/rustdoc/src-links-external.rs | 2 +- src/test/rustdoc/src-links.rs | 20 +- src/test/rustdoc/structfields.rs | 6 +- src/test/rustdoc/trait-self-link.rs | 2 +- src/test/rustdoc/tuples.rs | 6 +- src/test/rustdoc/variadic.rs | 2 +- src/test/rustdoc/where.rs | 18 +- 87 files changed, 620 insertions(+), 459 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 0211b2c9bc7ba..c8a68059bff88 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2727,7 +2727,7 @@ pub struct Macro { impl Clean for doctree::Macro { fn clean(&self, cx: &DocContext) -> Item { - let name = format!("{}!", self.name.clean(cx)); + let name = self.name.clean(cx); Item { name: Some(name.clone()), attrs: self.attrs.clean(cx), @@ -2738,8 +2738,10 @@ impl Clean for doctree::Macro { def_id: cx.map.local_def_id(self.id), inner: MacroItem(Macro { source: format!("macro_rules! {} {{\n{}}}", - name.trim_right_matches('!'), self.matchers.iter().map(|span| - format!(" {} => {{ ... }};\n", span.to_src(cx))).collect::()), + name, + self.matchers.iter().map(|span| { + format!(" {} => {{ ... }};\n", span.to_src(cx)) + }).collect::()), imported_from: self.imported_from.clean(cx), }), } diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index eed2615175b27..3f9cea86f0e00 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -326,9 +326,9 @@ pub fn href(did: DefId) -> Option<(String, ItemType, Vec)> { url.push_str("/index.html"); } _ => { - url.push_str(shortty.to_static_str()); - url.push_str("."); url.push_str(fqp.last().unwrap()); + url.push_str("."); + url.push_str(shortty.name_space().to_static_str()); url.push_str(".html"); } } @@ -382,7 +382,7 @@ fn primitive_link(f: &mut fmt::Formatter, Some(&LOCAL_CRATE) => { let len = CURRENT_LOCATION_KEY.with(|s| s.borrow().len()); let len = if len == 0 {0} else {len - 1}; - write!(f, "", + write!(f, "", repeat("../").take(len).collect::(), prim.to_url_str())?; needs_termination = true; @@ -397,7 +397,7 @@ fn primitive_link(f: &mut fmt::Formatter, (_, render::Unknown) => None, }; if let Some((cname, root)) = loc { - write!(f, "", + write!(f, "", root, cname, prim.to_url_str())?; @@ -439,7 +439,7 @@ impl<'a> fmt::Display for HRef<'a> { match href(self.did) { Some((url, shortty, fqp)) => { write!(f, "{}", - shortty, url, fqp.join("::"), self.text) + shortty.css_class(), url, fqp.join("::"), self.text) } _ => write!(f, "{}", self.text), } diff --git a/src/librustdoc/html/item_type.rs b/src/librustdoc/html/item_type.rs index 74f7b099044f1..c981849d87d43 100644 --- a/src/librustdoc/html/item_type.rs +++ b/src/librustdoc/html/item_type.rs @@ -42,6 +42,13 @@ 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 +97,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 +120,49 @@ 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, + } + } +} + +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 ItemType { +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/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..59a93fb610796 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; @@ -70,12 +70,12 @@ use html::format::{ConstnessSpace}; use html::format::{TyParamBounds, WhereClause, href, AbiSpace}; use html::format::{VisSpace, Method, UnsafetySpace, MutableSpace}; use html::format::fmt_impl_for_trait_page; -use html::item_type::ItemType; +use html::item_type::{self, ItemType}; use html::markdown::{self, Markdown}; use html::{highlight, layout}; -/// A pair of name and its optional document. -pub type NameDoc = (String, Option); +/// A triple of a name, its optional document, and an href. +pub type NameDoc = (String, Option, String); /// Major driving force in all rustdoc rendering. This contains information /// about where in the tree-like hierarchy rendering is occurring and controls @@ -92,8 +92,8 @@ pub struct Context { /// String representation of how to get back to the root path of the 'doc/' /// folder in terms of a relative URL. pub root_path: String, - /// The current destination folder of where HTML artifacts should be placed. - /// This changes as the context descends into the module hierarchy. + /// The destination folder for the current module. Where HTML artifacts + /// should be placed. This changes as we descend into the module hierarchy. pub dst: PathBuf, /// A flag, which when `true`, will render pages which redirect to the /// real location of an item. This is used to allow external links to @@ -313,6 +313,7 @@ struct IndexItem { name: String, path: String, desc: String, + href: Option, parent: Option, parent_idx: Option, search_type: Option, @@ -322,13 +323,14 @@ impl ToJson for IndexItem { fn to_json(&self) -> Json { assert_eq!(self.parent.is_some(), self.parent_idx.is_some()); - let mut data = Vec::with_capacity(6); + let mut data = Vec::with_capacity(7); data.push((self.ty as usize).to_json()); data.push(self.name.to_json()); data.push(self.path.to_json()); data.push(self.desc.to_json()); data.push(self.parent_idx.to_json()); data.push(self.search_type.to_json()); + data.push(self.href.to_json()); Json::Array(data) } @@ -428,10 +430,34 @@ pub fn derive_id(candidate: String) -> String { }) } -/// Generates the documentation for `crate` into the directory `dst` +fn href_for_item(item: &clean::Item, + mut path: String, + parent_path: Option) + -> Option { + let ty = item_type(item); + let name = match item.name.as_ref() { + Some(s) => s, + None => return None, + }; + let name_space = ty.name_space(); + + if !path.is_empty() && path.chars().last().unwrap() != '/' { + path.push('/'); + } + + Some(match (ty, parent_path) { + (ItemType::Module, _) => format!("{}{}/index.html", path, name), + (ItemType::ExternCrate, _) => format!("{}.{}.html", name, item_type::NAMESPACE_VALUE,), + (_, Some(parent_path)) => + format!("{}.{}.html#{}.{}", parent_path, item_type::NAMESPACE_TYPE, name, name_space), + (_, None) => format!("{}{}.{}.html", path, name, name_space), + }) +} + +/// Generates the documentation for `crate` into the directory `dst_root`. pub fn run(mut krate: clean::Crate, external_html: &ExternalHtml, - dst: PathBuf, + dst_root: PathBuf, passes: HashSet, css_file_extension: Option, renderinfo: RenderInfo) -> Result<(), Error> { @@ -490,12 +516,12 @@ pub fn run(mut krate: clean::Crate, } } } - try_err!(mkdir(&dst), &dst); - krate = render_sources(&dst, &mut scx, krate)?; + try_err!(mkdir(&dst_root), &dst_root); + krate = render_sources(&dst_root, &mut scx, krate)?; let cx = Context { current: Vec::new(), root_path: String::new(), - dst: dst, + dst: dst_root, render_redirect_pages: false, shared: Arc::new(scx), }; @@ -587,10 +613,11 @@ 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(), + href: href_for_item(item, fqp[..fqp.len() - 1].join("/"), Some(fqp.join("/"))), parent: Some(did), parent_idx: None, search_type: get_index_search_type(&item), @@ -707,17 +734,17 @@ fn write_shared(cx: &Context, write(cx.dst.join("COPYRIGHT.txt"), include_bytes!("static/COPYRIGHT.txt"))?; - fn collect(path: &Path, krate: &str, - key: &str) -> io::Result> { + fn collect_lines(path: &Path, krate: &str, + key: &str) -> io::Result> { let mut ret = Vec::new(); if path.exists() { 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()); } @@ -726,19 +753,20 @@ fn write_shared(cx: &Context, } // Update the search index - let dst = cx.dst.join("search-index.js"); - let all_indexes = try_err!(collect(&dst, &krate.name, "searchIndex"), &dst); - let mut w = try_err!(File::create(&dst), &dst); - try_err!(writeln!(&mut w, "var searchIndex = {{}};"), &dst); - try_err!(writeln!(&mut w, "{}", search_index), &dst); + let search_index_path = cx.dst.join("search-index.js"); + let all_indexes = try_err!(collect_lines(&search_index_path, &krate.name, "searchIndex"), + &search_index_path); + let mut w = try_err!(File::create(&search_index_path), &search_index_path); + try_err!(writeln!(&mut w, "var searchIndex = {{}};"), &search_index_path); + try_err!(writeln!(&mut w, "{}", search_index), &search_index_path); for index in &all_indexes { - try_err!(writeln!(&mut w, "{}", *index), &dst); + try_err!(writeln!(&mut w, "{}", *index), &search_index_path); } - try_err!(writeln!(&mut w, "initSearch(searchIndex);"), &dst); + try_err!(writeln!(&mut w, "initSearch(searchIndex);"), &search_index_path); // Update the list of all implementors for traits - let dst = cx.dst.join("implementors"); - try_err!(mkdir(&dst), &dst); + let impls_dir_path = cx.dst.join("implementors"); + try_err!(mkdir(&impls_dir_path), &impls_dir_path); for (&did, imps) in &cache.implementors { // Private modules can leak through to this phase of rustdoc, which // could contain implementations for otherwise private types. In some @@ -755,58 +783,59 @@ fn write_shared(cx: &Context, } }; - let mut mydst = dst.clone(); + let mut cur_impl_path = impls_dir_path.clone(); for part in &remote_path[..remote_path.len() - 1] { - mydst.push(part); - try_err!(mkdir(&mydst), &mydst); + cur_impl_path.push(part); + try_err!(mkdir(&cur_impl_path), &cur_impl_path); } - mydst.push(&format!("{}.{}.js", - remote_item_type.to_static_str(), - remote_path[remote_path.len() - 1])); - let all_implementors = try_err!(collect(&mydst, &krate.name, - "implementors"), - &mydst); + cur_impl_path.push(&format!("{}.{}.js", + remote_path[remote_path.len() - 1], + remote_item_type.name_space())); + let all_implementors = try_err!(collect_lines(&cur_impl_path, &krate.name, "implementors"), + &cur_impl_path); - try_err!(mkdir(mydst.parent().unwrap()), - &mydst.parent().unwrap().to_path_buf()); - let mut f = BufWriter::new(try_err!(File::create(&mydst), &mydst)); - try_err!(writeln!(&mut f, "(function() {{var implementors = {{}};"), &mydst); + try_err!(mkdir(cur_impl_path.parent().unwrap()), + &cur_impl_path.parent().unwrap().to_path_buf()); + let mut f = BufWriter::new(try_err!(File::create(&cur_impl_path), &cur_impl_path)); + try_err!(writeln!(&mut f, "(function() {{var implementors = {{}};"), &cur_impl_path); for implementor in &all_implementors { - try_err!(write!(&mut f, "{}", *implementor), &mydst); + try_err!(write!(&mut f, "{}", *implementor), &cur_impl_path); } - try_err!(write!(&mut f, r#"implementors["{}"] = ["#, krate.name), &mydst); + try_err!(write!(&mut f, r#"implementors["{}"] = ["#, krate.name), &cur_impl_path); for imp in imps { // 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_err!(write!(&mut f, r#""{}","#, imp.impl_), &mydst); + try_err!(write!(&mut f, r#""{}","#, imp.impl_), &cur_impl_path); } - try_err!(writeln!(&mut f, r"];"), &mydst); + try_err!(writeln!(&mut f, r"];"), &cur_impl_path); try_err!(writeln!(&mut f, "{}", r" if (window.register_implementors) { window.register_implementors(implementors); } else { window.pending_implementors = implementors; } - "), &mydst); - try_err!(writeln!(&mut f, r"}})()"), &mydst); + "), &cur_impl_path); + try_err!(writeln!(&mut f, r"}})()"), &cur_impl_path); } Ok(()) } -fn render_sources(dst: &Path, scx: &mut SharedContext, - krate: clean::Crate) -> Result { +fn render_sources(dst: &Path, + scx: &mut SharedContext, + krate: clean::Crate) + -> Result { info!("emitting source files"); - let dst = dst.join("src"); - try_err!(mkdir(&dst), &dst); - let dst = dst.join(&krate.name); - try_err!(mkdir(&dst), &dst); + let src_dir_path = dst.join("src"); + try_err!(mkdir(&src_dir_path), &src_dir_path); + let crate_dir_path = src_dir_path.join(&krate.name); + try_err!(mkdir(&crate_dir_path), &crate_dir_path); let mut folder = SourceCollector { - dst: dst, + dst: crate_dir_path, scx: scx, }; Ok(folder.fold_crate(krate)) @@ -832,7 +861,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) } @@ -901,8 +930,7 @@ impl<'a> DocFolder for SourceCollector<'a> { // something like that), so just don't include sources for the // entire crate. The other option is maintaining this mapping on a // per-file basis, but that's probably not worth it... - self.scx - .include_sources = match self.emit_source(&item.source.filename) { + self.scx.include_sources = match self.emit_source(&item.source.filename) { Ok(()) => true, Err(e) => { println!("warning: source code was requested to be rendered, \ @@ -952,7 +980,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 +989,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, @@ -1079,11 +1107,15 @@ impl DocFolder for Cache { // which should not be indexed. The crate-item itself is // inserted later on when serializing the search-index. if item.def_id.index != CRATE_DEF_INDEX { + let parent_path = parent.and_then(|pdid| { + self.paths.get(&pdid).map(|p| p.0.join("/")) + }); 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(), + href: href_for_item(&item, path.join("/"), parent_path), parent: parent, parent_idx: None, search_type: get_index_search_type(&item), @@ -1126,7 +1158,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 +1171,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))); } _ => {} @@ -1233,14 +1265,15 @@ impl<'a> Cache { } impl Context { - /// Recurse in the directory structure and change the "root path" to make - /// sure it always points to the top (relatively) + /// Recurse in the directory structure (into a module called `s`) and change + /// the "root path" to make sure it always points to the top (relatively). fn recurse(&mut self, s: String, f: F) -> T where - F: FnOnce(&mut Context) -> T, + F: FnOnce(&mut Context) -> T { if s.is_empty() { panic!("Unexpected empty destination: {:?}", self.current); } + let prev = self.dst.clone(); self.dst.push(&s); self.root_path.push_str("../"); @@ -1283,74 +1316,82 @@ 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(); - }); - 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()); + /// The rendering details for an item: writes docs for `it` to `writer`. + /// If `push_name` is true, then the name of the item is added to the page's + /// title. + fn render_item(&self, + writer: &mut io::Write, + it: &clean::Item, + push_name: 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 push_name { + 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 desc = if it.is_crate() { + format!("API documentation for the Rust `{}` crate.", + self.shared.layout.krate) + } else { + format!("API documentation for `{}` in crate `{}`.", + it.name.as_ref().unwrap(), self.shared.layout.krate) + }; + let keywords = make_item_keywords(it); + let page = layout::Page { + css_class: item_type(it).css_class(), + 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. @@ -1363,21 +1404,42 @@ impl Context { } if item.is_mod() { - // modules are special because they add a namespace. We also need to + // Modules are special because they add a namespace. We also need to // recurse into the items of the module as well. let name = item.name.as_ref().unwrap().to_string(); let mut item = Some(item); + self.recurse(name, |this| { let item = item.take().unwrap(); let mut buf = Vec::new(); - render(&mut buf, this, &item, false).unwrap(); - // buf will be empty if the module is stripped and there is no redirect for it + 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"); try_err!(fs::create_dir_all(&this.dst), &this.dst); + // The surrounding call to `recurse` adds the modules name to this.dst, so we + // only need to add 'index.html' to get the correct URL for the module. + let joint_dst = this.dst.join("index.html"); let mut dst = try_err!(File::create(&joint_dst), &joint_dst); try_err!(dst.write_all(&buf), &joint_dst); + + // Write a redirect from foo/bar/baz.t.html to foo/bar/baz/index.html + // since both are sensible ways to try and find a module's + // page. If a page exists already, do not overwrite it. We + // don't want to replace a real rustdoc page with a redirect. + // In particular, the redirect for a primitive module would + // overwrite the doc page for the primitive itself. + let mut redirect_dst = this.dst.clone(); + redirect_dst.pop(); + let name = item.name.as_ref().unwrap(); + redirect_dst.push(&format!("{}.t.html", name)); + if let Ok(mut redirect_out) = OpenOptions::new().create_new(true) + .write(true) + .open(&redirect_dst) { + let dst_url = format!("{}/index.html", name); + try_err!(layout::redirect(&mut redirect_out, &dst_url), &redirect_dst); + } } let m = match item.inner { @@ -1386,7 +1448,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"); @@ -1396,25 +1458,43 @@ impl Context { } for item in m.items { - f(this,item); + f(this, item); } + Ok(()) - }) + })?; } else if item.name.is_some() { let mut buf = Vec::new(); - render(&mut buf, self, &item, true).unwrap(); - // buf will be empty if the item is stripped and there is no redirect for it + 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())); + // `self.dst` contains the module path to the current item. We must therefore add + // the item's name and namespace indicator to get the full filename. + let name = item.name.as_ref().unwrap(); + let ty = item_type(&item); + let file_name = &item_path(ty, 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); + + // Emit a redirect from the old url for the page to the new page. + // E.g., `.../struct.Foo.html` to `.../Foo.t.html`. + let old_file_name = match ty { + ItemType::Macro => format!("{}.{}!.html", ty.css_class(), name), + _ => format!("{}.{}.html", ty.css_class(), name), + }; + let redirect_dst = self.dst.join(old_file_name); + if let Ok(mut redirect_out) = OpenOptions::new().create_new(true) + .write(true) + .open(&redirect_dst) { + try_err!(layout::redirect(&mut redirect_out, file_name), &redirect_dst); + } } - Ok(()) - } else { - Ok(()) } + + Ok(()) } fn build_sidebar_items(&self, m: &clean::Module) -> BTreeMap> { @@ -1423,14 +1503,16 @@ impl Context { for item in &m.items { if self.maybe_ignore_item(item) { continue } - let short = shortty(item).to_static_str(); let myname = match item.name { None => continue, Some(ref s) => s.to_string(), }; - let short = short.to_string(); - map.entry(short).or_insert(vec![]) - .push((myname, Some(plain_summary_line(item.doc_value())))); + let category = item_type(item).css_class().to_string(); + if let Some(href) = href_for_item(item, String::new(), None) { + map.entry(category) + .or_insert(vec![]) + .push((myname, Some(plain_summary_line(item.doc_value())), href)); + } } for (_, items) in &mut map { @@ -1531,7 +1613,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 +1648,7 @@ impl<'a> fmt::Display for Item<'a> { } } write!(fmt, "{}", - shortty(self.item), self.item.name.as_ref().unwrap())?; + item_type(self.item).css_class(), self.item.name.as_ref().unwrap())?; write!(fmt, "")?; // in-band write!(fmt, "")?; @@ -1622,7 +1704,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", name, ty.name_space().to_static_str()), } } @@ -1714,8 +1796,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 +1821,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 +1907,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).css_class(), 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 +2104,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!("{}.{}", name, item_type(m).name_space())); write!(w, "

", id = id, stab = m.stability_class())?; @@ -2095,7 +2177,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, } write!(w, "")?; write!(w, r#""#, root_path = vec![".."; cx.current.len()].join("/"), path = if it.def_id.is_local() { @@ -2104,7 +2186,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(), + namespace = item_type(it).name_space(), name = *it.name.as_ref().unwrap())?; Ok(()) } @@ -2113,12 +2195,12 @@ 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, }; - let anchor = format!("#{}.{}", ty, name); + let anchor = format!("#{}.{}", name, ty.name_space()); match link { AssocItemLink::Anchor(Some(ref id)) => format!("#{}", id), AssocItemLink::Anchor(None) => anchor, @@ -2191,7 +2273,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!("#{}.{}", name, item_type(meth).name_space()); let href = match link { AssocItemLink::Anchor(Some(ref id)) => format!("#{}", id), AssocItemLink::Anchor(None) => anchor, @@ -2204,7 +2286,7 @@ fn render_assoc_item(w: &mut fmt::Formatter, ItemType::TyMethod }; - href(did).map(|p| format!("{}#{}.{}", p.0, ty, name)).unwrap_or(anchor) + href(did).map(|p| format!("{}#{}.{}", p.0, name, ty.name_space())).unwrap_or(anchor) } }; // FIXME(#24111): remove when `const_fn` is stabilized @@ -2268,9 +2350,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} - ", - shortty = ItemType::StructField, + write!(w, + " + {name}: {ty} + ", + item_class = ItemType::StructField.css_class(), + namespace = item_type::NAMESPACE_VALUE, stab = field.stability_class(), name = field.name.as_ref().unwrap(), ty = ty)?; @@ -2339,8 +2424,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}", + namespace = item_type::NAMESPACE_VALUE, name = variant.name.as_ref().unwrap())?; if let clean::VariantItem(ref var) = variant.inner { if let clean::TupleVariant(ref tys) = var.kind { @@ -2365,8 +2450,9 @@ fn item_enum(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, use clean::StructFieldItem; if let StructFieldItem(ref ty) = field.inner { write!(w, "\ + id='{v}.{namespace}.{f}.{namespace}'>\ {f}: {t}", + namespace = item_type::NAMESPACE_VALUE, v = variant.name.as_ref().unwrap(), f = field.name.as_ref().unwrap(), t = *ty)?; @@ -2588,7 +2674,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 +2687,10 @@ 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!("{}.{}", name, item_type.name_space())); + let old_id = derive_id(format!("{}.{}", item_type.css_class(), name)); + write!(w, "

", + id, item_type.css_class(), old_id)?; write!(w, "")?; render_assoc_item(w, item, link.anchor(&id))?; write!(w, "")?; @@ -2611,26 +2699,35 @@ 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)?; + let id = derive_id(format!("{}.{}", name, ItemType::AssociatedType.name_space())); + let old_id = derive_id(format!("{}.{}", + ItemType::AssociatedType.css_class(), name)); + write!(w, "

", + id, item_type.css_class(), old_id)?; 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!("{}.{}", name, item_type.name_space())); + let old_id = derive_id(format!("{}.{}", item_type.css_class(), name)); + write!(w, "

", + id, item_type.css_class(), old_id)?; 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!("{}.{}", name, item_type.name_space())); + let old_id = derive_id(format!("{}.{}", item_type.css_class(), name)); + write!(w, "

", + id, item_type.css_class(), old_id)?; 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!("{}.{}", name, item_type.name_space())); + let old_id = derive_id(format!("{}.{}", item_type.css_class(), name)); + write!(w, "

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

\n")?; } @@ -2744,13 +2841,13 @@ impl<'a> fmt::Display for Sidebar<'a> { let relpath = if it.is_mod() { "../" } else { "" }; write!(fmt, "", - name = it.name.as_ref().map(|x| &x[..]).unwrap_or(""), - ty = shortty(it).to_static_str(), - path = relpath)?; + name = it.name.as_ref().map(|x| &**x).unwrap_or(""), + css_class = item_type(it).css_class(), + relpath = relpath)?; if parentlen == 0 { // there is no sidebar-items.js beyond the crate root path // FIXME maybe dynamic crate loading can be merged here diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 68035e5abe4c2..0a249f82c29b7 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -39,6 +39,39 @@ // used for special search precedence var TY_PRIMITIVE = itemTypes.indexOf("primitive"); + // Which namespace the various item types belong to. + var NS_TYPE = ["mod", + "struct", + "enum", + "type", + "trait", + "primitive", + "associatedtype"]; + var NS_VALUE = ["externcrate", + "import", + "fn", + "static", + "impl", + "tymethod", + "method", + "structfield", + "variant", + "constant", + "associatedconstant"]; + var NS_MACRO = ["macro"]; + function nsForType(type) { + if (NS_TYPE.indexOf(type) >= 0) { + return "t"; + } else if (NS_VALUE.indexOf(type) >= 0) { + return "v"; + } else if (NS_MACRO.indexOf(type) >= 0) { + return "m"; + } else { + // bug + return ""; + } + } + $('.js-only').removeClass('js-only'); function getQueryStringParams() { @@ -563,50 +596,35 @@ shown = []; results.forEach(function(item) { - var name, type, href, displayPath; - if (shown.indexOf(item) !== -1) { return; } shown.push(item); - name = item.name; - type = itemTypes[item.ty]; + var type = itemTypes[item.ty]; + var displayPath; if (type === 'mod') { displayPath = item.path + '::'; - href = rootPath + item.path.replace(/::/g, '/') + '/' + - name + '/index.html'; - } else if (type === 'static' || type === 'reexport') { + } else if (type === 'static') { displayPath = item.path + '::'; - href = rootPath + item.path.replace(/::/g, '/') + - '/index.html'; } else if (type === "primitive") { displayPath = ""; - href = rootPath + item.path.replace(/::/g, '/') + - '/' + type + '.' + name + '.html'; } else if (type === "externcrate") { displayPath = ""; - href = rootPath + name + '/index.html'; } else if (item.parent !== undefined) { var myparent = item.parent; - var anchor = '#' + type + '.' + name; displayPath = item.path + '::' + myparent.name + '::'; - href = rootPath + item.path.replace(/::/g, '/') + - '/' + itemTypes[myparent.ty] + - '.' + myparent.name + - '.html' + anchor; } else { displayPath = item.path + '::'; - href = rootPath + item.path.replace(/::/g, '/') + - '/' + type + '.' + name + '.html'; } + var name = item.name; output += '' + - '' + + '' + displayPath + '' + name + '' + - '' + + '' + '' + item.desc + ' '; }); @@ -700,8 +718,9 @@ // (String) name, // (String) full path or empty string for previous path, // (String) description, - // (Number | null) the parent path index to `paths`] - // (Object | null) the type of the function (if any) + // (Number | null) the parent path index to `paths`], + // (Object | null) the type of the function (if any), + // (String) href for the item. var items = rawSearchIndex[crate].items; // an array of [(Number) item type, // (String) name] @@ -726,7 +745,7 @@ var rawRow = items[i]; var row = {crate: crate, ty: rawRow[0], name: rawRow[1], path: rawRow[2] || lastPath, desc: rawRow[3], - parent: paths[rawRow[4]], type: rawRow[5]}; + parent: paths[rawRow[4]], type: rawRow[5], href: rawRow[6]}; searchIndex.push(row); if (typeof row.name === "string") { var word = row.name.toLowerCase(); @@ -867,16 +886,11 @@ var desc = item[1]; // can be null var klass = shortty; - if (name === current.name && shortty === current.ty) { + if (name === current.name && shortty === current.cssClass) { klass += ' current'; } - var path; - if (shortty === 'mod') { - path = name + '/index.html'; - } else { - path = shortty + '.' + name + '.html'; - } - var link = $('', {'href': current.relpath + path, + console.log(item); + var link = $('', {'href': current.relpath + item[2], 'title': desc, 'class': klass}).text(name); ul.append($('
  • ').append(link)); diff --git a/src/test/rustdoc/assoc-consts.rs b/src/test/rustdoc/assoc-consts.rs index 8d3f9b59bb2ee..2eeda88a895b5 100644 --- a/src/test/rustdoc/assoc-consts.rs +++ b/src/test/rustdoc/assoc-consts.rs @@ -11,16 +11,16 @@ #![feature(associated_consts)] pub trait Foo { - // @has assoc_consts/trait.Foo.html '//*[@class="rust trait"]' \ + // @has assoc_consts/Foo.t.html '//*[@class="rust trait"]' \ // 'const FOO: usize;' - // @has - '//*[@id="associatedconstant.FOO"]' 'const FOO' + // @has - '//*[@id="FOO.v"]' 'const FOO' const FOO: usize; } pub struct Bar; impl Bar { - // @has assoc_consts/struct.Bar.html '//*[@id="associatedconstant.BAR"]' \ + // @has assoc_consts/Bar.t.html '//*[@id="BAR.v"]' \ // 'const BAR: usize = 3' pub const BAR: usize = 3; } diff --git a/src/test/rustdoc/assoc-types.rs b/src/test/rustdoc/assoc-types.rs index d5047ade062dc..46ea204f4384c 100644 --- a/src/test/rustdoc/assoc-types.rs +++ b/src/test/rustdoc/assoc-types.rs @@ -10,16 +10,16 @@ #![crate_type="lib"] -// @has assoc_types/trait.Index.html +// @has assoc_types/Index.t.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="tymethod.index"]//code' \ + // @has - '//*[@id="index.v"]//code' \ // "fn index<'a>(&'a self, index: I) -> &'a Self::Output" fn index<'a>(&'a self, index: I) -> &'a Self::Output; } -// @has assoc_types/fn.use_output.html +// @has assoc_types/use_output.v.html // @has - '//*[@class="rust fn"]' '-> &T::Output' pub fn use_output>(obj: &T, index: usize) -> &T::Output { obj.index(index) @@ -29,11 +29,11 @@ pub trait Feed { type Input; } -// @has assoc_types/fn.use_input.html +// @has assoc_types/use_input.v.html // @has - '//*[@class="rust fn"]' 'T::Input' pub fn use_input(_feed: &T, _element: T::Input) { } -// @has assoc_types/fn.cmp_input.html +// @has assoc_types/cmp_input.v.html // @has - '//*[@class="rust fn"]' 'where T::Input: PartialEq' pub fn cmp_input(a: &T::Input, b: &U::Input) -> bool where T::Input: PartialEq diff --git a/src/test/rustdoc/cap-lints.rs b/src/test/rustdoc/cap-lints.rs index e7f308a6f0b69..6c6623b779cd2 100644 --- a/src/test/rustdoc/cap-lints.rs +++ b/src/test/rustdoc/cap-lints.rs @@ -13,7 +13,7 @@ // therefore should not concern itself with the lints. #[deny(warnings)] -// @has cap_lints/struct.foo.html //pre '#[must_use]' +// @has cap_lints/foo.t.html //pre '#[must_use]' #[must_use] pub struct foo { field: i32, diff --git a/src/test/rustdoc/deprecated-impls.rs b/src/test/rustdoc/deprecated-impls.rs index bcf0645766b30..05fc4e513aa49 100644 --- a/src/test/rustdoc/deprecated-impls.rs +++ b/src/test/rustdoc/deprecated-impls.rs @@ -10,7 +10,7 @@ #![crate_name = "foo"] -// @has foo/struct.Foo0.html +// @has foo/Foo0.t.html pub struct Foo0; impl Foo0 { @@ -57,7 +57,7 @@ pub trait Bar { fn fn_def_def_without_doc() {} } -// @has foo/struct.Foo1.html +// @has foo/Foo1.t.html pub struct Foo1; impl Bar for Foo1 { @@ -90,7 +90,7 @@ impl Bar for Foo1 { // @has - '//*[@class="stab deprecated"]' 'Deprecated since 1.0.8: fn_def_def_without_doc' } -// @has foo/struct.Foo2.html +// @has foo/Foo2.t.html pub struct Foo2; impl Bar for Foo2 { diff --git a/src/test/rustdoc/deprecated.rs b/src/test/rustdoc/deprecated.rs index 744304a62c216..8883c424c3178 100644 --- a/src/test/rustdoc/deprecated.rs +++ b/src/test/rustdoc/deprecated.rs @@ -10,7 +10,7 @@ #![feature(deprecated)] -// @has deprecated/struct.S.html '//*[@class="stab deprecated"]' \ +// @has deprecated/S.t.html '//*[@class="stab deprecated"]' \ // 'Deprecated since 1.0.0: text' #[deprecated(since = "1.0.0", note = "text")] pub struct S; diff --git a/src/test/rustdoc/duplicate_impls/issue-33054.rs b/src/test/rustdoc/duplicate_impls/issue-33054.rs index df6ebcae10756..c8a3dff82de41 100644 --- a/src/test/rustdoc/duplicate_impls/issue-33054.rs +++ b/src/test/rustdoc/duplicate_impls/issue-33054.rs @@ -8,11 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// @has issue_33054/impls/struct.Foo.html +// @has issue_33054/impls/Foo.t.html // @has - '//code' 'impl Foo' // @has - '//code' 'impl Bar for Foo' // @count - '//*[@class="impl"]' 2 -// @has issue_33054/impls/bar/trait.Bar.html +// @has issue_33054/impls/bar/Bar.t.html // @has - '//code' 'impl Bar for Foo' // @count - '//*[@class="struct"]' 1 pub mod impls; diff --git a/src/test/rustdoc/escape-rust-expr.rs b/src/test/rustdoc/escape-rust-expr.rs index 7f9a2bf175a5f..977c66c327d21 100644 --- a/src/test/rustdoc/escape-rust-expr.rs +++ b/src/test/rustdoc/escape-rust-expr.rs @@ -11,5 +11,5 @@ // Test that we HTML-escape Rust expressions, where HTML special chars // can occur, and we know it's definitely not markup. -// @has escape_rust_expr/constant.CONST_S.html '//pre[@class="rust const"]' '"