From 525b77e9aeb93eac90a8b0abc3efa3fd6a6fe8ed Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 3 Aug 2016 13:56:18 +1200 Subject: [PATCH] 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)