diff options
Diffstat (limited to 'src/librustdoc/html/format.rs')
| -rw-r--r-- | src/librustdoc/html/format.rs | 146 |
1 files changed, 69 insertions, 77 deletions
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 9c22837bdae..313734e3fdd 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -6,6 +6,7 @@ //! them in the future to instead emit any format desired. use std::borrow::Cow; +use std::cell::Cell; use std::fmt; use rustc::hir::def_id::DefId; @@ -15,7 +16,7 @@ use rustc::hir; use crate::clean::{self, PrimitiveType}; use crate::html::item_type::ItemType; -use crate::html::render::{self, cache, CURRENT_LOCATION_KEY}; +use crate::html::render::{self, cache, CURRENT_DEPTH}; /// Helper to render an optional visibility with a space after it (if the /// visibility is preset) @@ -36,13 +37,8 @@ pub struct AsyncSpace(pub hir::IsAsync); /// Similar to VisSpace, but used for mutability #[derive(Copy, Clone)] pub struct MutableSpace(pub clean::Mutability); -/// Similar to VisSpace, but used for mutability -#[derive(Copy, Clone)] -pub struct RawMutableSpace(pub clean::Mutability); /// Wrapper struct for emitting type parameter bounds. pub struct GenericBounds<'a>(pub &'a [clean::GenericBound]); -/// Wrapper struct for emitting a comma-separated list of items -pub struct CommaSep<'a, T>(pub &'a [T]); pub struct AbiSpace(pub Abi); pub struct DefaultSpace(pub bool); @@ -71,11 +67,6 @@ pub struct WhereClause<'a>{ pub end_newline: bool, } -pub struct HRef<'a> { - pub did: DefId, - pub text: &'a str, -} - impl<'a> VisSpace<'a> { pub fn get(self) -> &'a Option<clean::Visibility> { let VisSpace(v) = self; v @@ -94,14 +85,14 @@ impl ConstnessSpace { } } -impl<'a, T: fmt::Display> fmt::Display for CommaSep<'a, T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - for (i, item) in self.0.iter().enumerate() { +fn comma_sep<T: fmt::Display>(items: &[T]) -> impl fmt::Display + '_ { + display_fn(move |f| { + for (i, item) in items.iter().enumerate() { if i != 0 { write!(f, ", ")?; } fmt::Display::fmt(item, f)?; } Ok(()) - } + }) } impl<'a> fmt::Display for GenericBounds<'a> { @@ -168,9 +159,9 @@ impl fmt::Display for clean::Generics { return Ok(()); } if f.alternate() { - write!(f, "<{:#}>", CommaSep(&real_params)) + write!(f, "<{:#}>", comma_sep(&real_params)) } else { - write!(f, "<{}>", CommaSep(&real_params)) + write!(f, "<{}>", comma_sep(&real_params)) } } } @@ -268,9 +259,9 @@ impl fmt::Display for clean::PolyTrait { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if !self.generic_params.is_empty() { if f.alternate() { - write!(f, "for<{:#}> ", CommaSep(&self.generic_params))?; + write!(f, "for<{:#}> ", comma_sep(&self.generic_params))?; } else { - write!(f, "for<{}> ", CommaSep(&self.generic_params))?; + write!(f, "for<{}> ", comma_sep(&self.generic_params))?; } } if f.alternate() { @@ -407,16 +398,16 @@ pub fn href(did: DefId) -> Option<(String, ItemType, Vec<String>)> { return None } - let loc = CURRENT_LOCATION_KEY.with(|l| l.borrow().clone()); + let depth = CURRENT_DEPTH.with(|l| l.get()); let (fqp, shortty, mut url) = match cache.paths.get(&did) { Some(&(ref fqp, shortty)) => { - (fqp, shortty, "../".repeat(loc.len())) + (fqp, shortty, "../".repeat(depth)) } None => { let &(ref fqp, shortty) = cache.external_paths.get(&did)?; (fqp, shortty, match cache.extern_locations[&did.krate] { (.., render::Remote(ref s)) => s.to_string(), - (.., render::Local) => "../".repeat(loc.len()), + (.., render::Local) => "../".repeat(depth), (.., render::Unknown) => return None, }) } @@ -452,19 +443,18 @@ fn resolved_path(w: &mut fmt::Formatter<'_>, did: DefId, path: &clean::Path, } } if w.alternate() { - write!(w, "{:#}{:#}", HRef::new(did, &last.name), last.args)?; + write!(w, "{}{:#}", &last.name, last.args)?; } else { let path = if use_absolute { - match href(did) { - Some((_, _, fqp)) => { - format!("{}::{}", - fqp[..fqp.len() - 1].join("::"), - HRef::new(did, fqp.last().unwrap())) - } - None => HRef::new(did, &last.name).to_string(), + if let Some((_, _, fqp)) = href(did) { + format!("{}::{}", + fqp[..fqp.len() - 1].join("::"), + anchor(did, fqp.last().unwrap())) + } else { + last.name.to_string() } } else { - HRef::new(did, &last.name).to_string() + anchor(did, &last.name).to_string() }; write!(w, "{}{}", path, last.args)?; } @@ -479,7 +469,7 @@ fn primitive_link(f: &mut fmt::Formatter<'_>, if !f.alternate() { match m.primitive_locations.get(&prim) { Some(&def_id) if def_id.is_local() => { - let len = CURRENT_LOCATION_KEY.with(|s| s.borrow().len()); + let len = CURRENT_DEPTH.with(|s| s.get()); let len = if len == 0 {0} else {len - 1}; write!(f, "<a class=\"primitive\" href=\"{}primitive.{}.html\">", "../".repeat(len), @@ -492,7 +482,7 @@ fn primitive_link(f: &mut fmt::Formatter<'_>, Some((cname, s.to_string())) } (ref cname, _, render::Local) => { - let len = CURRENT_LOCATION_KEY.with(|s| s.borrow().len()); + let len = CURRENT_DEPTH.with(|s| s.get()); Some((cname, "../".repeat(len))) } (.., render::Unknown) => None, @@ -516,38 +506,30 @@ fn primitive_link(f: &mut fmt::Formatter<'_>, } /// Helper to render type parameters -fn tybounds(w: &mut fmt::Formatter<'_>, - param_names: &Option<Vec<clean::GenericBound>>) -> fmt::Result { - match *param_names { - Some(ref params) => { - for param in params { - write!(w, " + ")?; - fmt::Display::fmt(param, w)?; +fn tybounds(param_names: &Option<Vec<clean::GenericBound>>) -> impl fmt::Display + '_ { + display_fn(move |f| { + match *param_names { + Some(ref params) => { + for param in params { + write!(f, " + ")?; + fmt::Display::fmt(param, f)?; + } + Ok(()) } - Ok(()) + None => Ok(()) } - None => Ok(()) - } -} - -impl<'a> HRef<'a> { - pub fn new(did: DefId, text: &'a str) -> HRef<'a> { - HRef { did: did, text: text } - } + }) } -impl<'a> fmt::Display for HRef<'a> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match href(self.did) { - Some((url, shortty, fqp)) => if !f.alternate() { - write!(f, "<a class=\"{}\" href=\"{}\" title=\"{} {}\">{}</a>", - shortty, url, shortty, fqp.join("::"), self.text) - } else { - write!(f, "{}", self.text) - }, - _ => write!(f, "{}", self.text), +pub fn anchor(did: DefId, text: &str) -> impl fmt::Display + '_ { + display_fn(move |f| { + if let Some((url, short_ty, fqp)) = href(did) { + write!(f, r#"<a class="{}" href="{}" title="{} {}">{}</a>"#, + short_ty, url, short_ty, fqp.join("::"), text) + } else { + write!(f, "{}", text) } - } + }) } fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter<'_>, use_absolute: bool) -> fmt::Result { @@ -561,7 +543,7 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter<'_>, use_absolute: bool) -> } // Paths like `T::Output` and `Self::Output` should be rendered with all segments. resolved_path(f, did, path, is_generic, use_absolute)?; - tybounds(f, param_names) + fmt::Display::fmt(&tybounds(param_names), f) } clean::Infer => write!(f, "_"), clean::Primitive(prim) => primitive_link(f, prim, prim.as_str()), @@ -570,12 +552,12 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter<'_>, use_absolute: bool) -> write!(f, "{}{:#}fn{:#}{:#}", UnsafetySpace(decl.unsafety), AbiSpace(decl.abi), - CommaSep(&decl.generic_params), + comma_sep(&decl.generic_params), decl.decl) } else { write!(f, "{}{}", UnsafetySpace(decl.unsafety), AbiSpace(decl.abi))?; primitive_link(f, PrimitiveType::Fn, "fn")?; - write!(f, "{}{}", CommaSep(&decl.generic_params), decl.decl) + write!(f, "{}{}", comma_sep(&decl.generic_params), decl.decl) } } clean::Tuple(ref typs) => { @@ -589,7 +571,7 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter<'_>, use_absolute: bool) -> } many => { primitive_link(f, PrimitiveType::Tuple, "(")?; - fmt::Display::fmt(&CommaSep(many), f)?; + fmt::Display::fmt(&comma_sep(many), f)?; primitive_link(f, PrimitiveType::Tuple, ")") } } @@ -607,19 +589,22 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter<'_>, use_absolute: bool) -> clean::Never => primitive_link(f, PrimitiveType::Never, "!"), clean::CVarArgs => primitive_link(f, PrimitiveType::CVarArgs, "..."), clean::RawPointer(m, ref t) => { + let m = match m { + clean::Immutable => "const", + clean::Mutable => "mut", + }; match **t { clean::Generic(_) | clean::ResolvedPath {is_generic: true, ..} => { if f.alternate() { primitive_link(f, clean::PrimitiveType::RawPointer, - &format!("*{}{:#}", RawMutableSpace(m), t)) + &format!("*{} {:#}", m, t)) } else { primitive_link(f, clean::PrimitiveType::RawPointer, - &format!("*{}{}", RawMutableSpace(m), t)) + &format!("*{} {}", m, t)) } } _ => { - primitive_link(f, clean::PrimitiveType::RawPointer, - &format!("*{}", RawMutableSpace(m)))?; + primitive_link(f, clean::PrimitiveType::RawPointer, &format!("*{} ", m))?; fmt::Display::fmt(t, f) } } @@ -1047,15 +1032,6 @@ impl fmt::Display for MutableSpace { } } -impl fmt::Display for RawMutableSpace { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match *self { - RawMutableSpace(clean::Immutable) => write!(f, "const "), - RawMutableSpace(clean::Mutable) => write!(f, "mut "), - } - } -} - impl fmt::Display for AbiSpace { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let quot = if f.alternate() { "\"" } else { """ }; @@ -1075,3 +1051,19 @@ impl fmt::Display for DefaultSpace { } } } + +crate fn display_fn( + f: impl FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, +) -> impl fmt::Display { + WithFormatter(Cell::new(Some(f))) +} + +struct WithFormatter<F>(Cell<Option<F>>); + +impl<F> fmt::Display for WithFormatter<F> + where F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + (self.0.take()).unwrap()(f) + } +} |
