From f35eae9934c227a094e23c378a330b03b9d2ec01 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Tue, 27 Aug 2019 17:09:13 -0400 Subject: [PATCH 01/17] Add buffer abstraction --- src/librustdoc/html/format.rs | 65 +++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 313734e3fdd6b..941d2c4acb1a8 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -18,6 +18,71 @@ use crate::clean::{self, PrimitiveType}; use crate::html::item_type::ItemType; use crate::html::render::{self, cache, CURRENT_DEPTH}; +pub trait Print { + fn print(&self, buffer: &mut Buffer); +} + +#[derive(Debug, Clone)] +pub struct Buffer { + for_html: bool, + buffer: String, +} + +impl Buffer { + crate fn empty_from(v: &Buffer) -> Buffer { + Buffer { + for_html: v.for_html, + buffer: String::new(), + } + } + + crate fn html() -> Buffer { + Buffer { + for_html: true, + buffer: String::new(), + } + } + + crate fn is_empty(&self) -> bool { + self.buffer.is_empty() + } + + crate fn into_inner(self) -> String { + self.buffer + } + + crate fn insert_str(&mut self, idx: usize, s: &str) { + self.buffer.insert_str(idx, s); + } + + crate fn push_str(&mut self, s: &str) { + self.buffer.push_str(s); + } + + // Intended for consumption by write! and writeln! (std::fmt) but without + // the fmt::Result return type imposed by fmt::Write (and avoiding the trait + // import). + crate fn write_str(&mut self, s: &str) { + self.buffer.push_str(s); + } + + // Intended for consumption by write! and writeln! (std::fmt) but without + // the fmt::Result return type imposed by fmt::Write (and avoiding the trait + // import). + crate fn write_fmt(&mut self, v: fmt::Arguments<'_>) { + use fmt::Write; + self.buffer.write_fmt(v).unwrap(); + } + + crate fn display(&mut self, t: T) { + if self.for_html { + write!(self, "{}", t); + } else { + write!(self, "{:#}", t); + } + } +} + /// Helper to render an optional visibility with a space after it (if the /// visibility is preset) #[derive(Copy, Clone)] From eebd0265c328b80d67f89df04879ef64bd229a5f Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Fri, 30 Aug 2019 10:24:42 -0400 Subject: [PATCH 02/17] Migrate top-level rendering to Buffer --- src/librustdoc/html/layout.rs | 8 ++-- src/librustdoc/html/render.rs | 83 +++++++++++++++++----------------- src/librustdoc/html/sources.rs | 10 ++-- 3 files changed, 49 insertions(+), 52 deletions(-) diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index ae0bd1aafa8f1..2856db7ef9843 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -1,9 +1,9 @@ use std::fmt; -use std::io; use std::path::PathBuf; use crate::externalfiles::ExternalHtml; use crate::html::render::SlashChecker; +use crate::html::format::Buffer; #[derive(Clone)] pub struct Layout { @@ -26,7 +26,7 @@ pub struct Page<'a> { } pub fn render( - dst: &mut dyn io::Write, + dst: &mut Buffer, layout: &Layout, page: &Page<'_>, sidebar: &S, @@ -34,7 +34,7 @@ pub fn render( css_file_extension: bool, themes: &[PathBuf], generate_search_filter: bool, -) -> io::Result<()> { +) { let static_root_path = page.static_root_path.unwrap_or(page.root_path); write!(dst, "\ @@ -238,7 +238,7 @@ pub fn render( ) } -pub fn redirect(dst: &mut dyn io::Write, url: &str) -> io::Result<()> { +pub fn redirect(dst: &mut Buffer, url: &str) { // \ \ ", - css_extension = if css_file_extension { + css_extension = if layout.css_file_extension.is_some() { format!("", @@ -228,7 +232,7 @@ pub fn render( root_path=page.root_path, extra_script=e) }).collect::(), - filter_crates=if generate_search_filter { + filter_crates=if layout.generate_search_filter { "" diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index c9483088b7b1b..1da862315bc98 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -192,9 +192,6 @@ crate struct SharedContext { /// The base-URL of the issue tracker for when an item has been tagged with /// an issue number. pub issue_tracker_base_url: Option, - /// The given user css file which allow to customize the generated - /// documentation theme. - pub css_file_extension: Option, /// The directories that have already been created in this doc run. Used to reduce the number /// of spurious `create_dir_all` calls. pub created_dirs: RefCell>, @@ -209,9 +206,6 @@ crate struct SharedContext { /// Optional path string to be used to load static files on output pages. If not set, uses /// combinations of `../` to reach the documentation root. pub static_root_path: Option, - /// If false, the `select` element to have search filtering by crates on rendered docs - /// won't be generated. - pub generate_search_filter: bool, /// Option disabled by default to generate files used by RLS and some other tools. pub generate_redirect_pages: bool, /// The fs handle we are working with. @@ -545,14 +539,14 @@ pub fn run(mut krate: clean::Crate, favicon: String::new(), external_html, krate: krate.name.clone(), + css_file_extension: extension_css, + generate_search_filter, }, - css_file_extension: extension_css, created_dirs: Default::default(), sort_modules_alphabetically, themes, resource_suffix, static_root_path, - generate_search_filter, generate_redirect_pages, fs: DocFS::new(&errors), }; @@ -932,7 +926,7 @@ themePicker.onblur = handleThemeButtonsBlur; options.enable_minification)?; } - if let Some(ref css) = cx.shared.css_file_extension { + if let Some(ref css) = cx.shared.layout.css_file_extension { let out = cx.dst.join(&format!("theme{}.css", cx.shared.resource_suffix)); let buffer = try_err!(fs::read_to_string(css), css); if !options.enable_minification { @@ -1187,9 +1181,7 @@ themePicker.onblur = handleThemeButtonsBlur; .collect::()); let v = layout::render(&cx.shared.layout, &page, &(""), &content, - cx.shared.css_file_extension.is_some(), - &cx.shared.themes, - cx.shared.generate_search_filter); + &cx.shared.themes); cx.shared.fs.write(&dst, v.as_bytes())?; } } @@ -1940,9 +1932,7 @@ impl Context { }; let v = layout::render(&self.shared.layout, &page, &sidebar, &all, - self.shared.css_file_extension.is_some(), - &self.shared.themes, - self.shared.generate_search_filter); + &self.shared.themes); self.shared.fs.write(&final_file, v.as_bytes())?; // Generating settings page. @@ -1958,10 +1948,7 @@ impl Context { let v = layout::render( &self.shared.layout, &page, &sidebar, &settings, - self.shared.css_file_extension.is_some(), - &themes, - self.shared.generate_search_filter, - ); + &themes); self.shared.fs.write(&settings_file, v.as_bytes())?; Ok(()) @@ -2019,9 +2006,7 @@ impl Context { layout::render(&self.shared.layout, &page, &Sidebar{ cx: self, item: it }, &Item{ cx: self, item: it }, - self.shared.css_file_extension.is_some(), - &self.shared.themes, - self.shared.generate_search_filter) + &self.shared.themes) } else { let mut url = self.root_path(); if let Some(&(ref names, ty)) = cache().paths.get(&it.def_id) { diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs index d3e006447415b..018db3f9363cb 100644 --- a/src/librustdoc/html/sources.rs +++ b/src/librustdoc/html/sources.rs @@ -121,9 +121,7 @@ impl<'a> SourceCollector<'a> { }; let v = layout::render(&self.scx.layout, &page, &(""), &Source(contents), - self.scx.css_file_extension.is_some(), - &self.scx.themes, - self.scx.generate_search_filter); + &self.scx.themes); self.scx.fs.write(&cur, v.as_bytes())?; self.scx.local_sources.insert(p.clone(), href); Ok(()) From 75528f266fc5b3b3f7acc8fbd3c51ce78ccd7dcd Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sat, 31 Aug 2019 08:45:44 -0400 Subject: [PATCH 06/17] Replace writeln!/write! with push_str --- src/librustdoc/html/render.rs | 150 ++++++++++++++++------------------ 1 file changed, 69 insertions(+), 81 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 1da862315bc98..09c2e31b4ed6b 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -65,7 +65,7 @@ use crate::docfs::{DocFS, ErrorStorage, PathError}; use crate::doctree; use crate::fold::DocFolder; use crate::html::escape::Escape; -use crate::html::format::{AsyncSpace, ConstnessSpace}; +use crate::html::format::{Buffer, AsyncSpace, ConstnessSpace}; use crate::html::format::{GenericBounds, WhereClause, href, AbiSpace, DefaultSpace}; use crate::html::format::{VisSpace, Function, UnsafetySpace, MutableSpace}; use crate::html::format::fmt_impl_for_trait_page; @@ -1025,12 +1025,12 @@ themePicker.onblur = handleThemeButtonsBlur; } all_aliases.push(format!("ALIASES[\"{}\"] = {{{}}};", krate.name, output)); all_aliases.sort(); - let mut v = Vec::new(); - try_err!(writeln!(&mut v, "var ALIASES = {{}};"), &dst); + let mut v = Buffer::html(); + writeln!(&mut v, "var ALIASES = {{}};"); for aliases in &all_aliases { - try_err!(writeln!(&mut v, "{}", aliases), &dst); + writeln!(&mut v, "{}", aliases); } - cx.shared.fs.write(&dst, &v)?; + cx.shared.fs.write(&dst, v.into_inner().into_bytes())?; } use std::ffi::OsString; @@ -1114,12 +1114,9 @@ themePicker.onblur = handleThemeButtonsBlur; &krate.name, hierarchy.to_json_string())); all_sources.sort(); - let mut v = Vec::new(); - try_err!(writeln!(&mut v, - "var N = null;var sourcesIndex = {{}};\n{}\ncreateSourceSidebar();", - all_sources.join("\n")), - &dst); - cx.shared.fs.write(&dst, &v)?; + let v = format!("var N = null;var sourcesIndex = {{}};\n{}\ncreateSourceSidebar();\n", + all_sources.join("\n")); + cx.shared.fs.write(&dst, v.as_bytes())?; } // Update the search index @@ -1134,14 +1131,11 @@ themePicker.onblur = handleThemeButtonsBlur; // with rustdoc running in parallel. all_indexes.sort(); { - let mut v = Vec::new(); - try_err!(writeln!(&mut v, "var N=null,E=\"\",T=\"t\",U=\"u\",searchIndex={{}};"), &dst); - try_err!(write_minify_replacer( - &mut v, + let mut v = String::from("var N=null,E=\"\",T=\"t\",U=\"u\",searchIndex={};\n"); + v.push_str(&minify_replacer( &format!("{}\n{}", variables.join(""), all_indexes.join("\n")), - options.enable_minification), - &dst); - try_err!(write!(&mut v, "initSearch(searchIndex);addSearchOptions(searchIndex);"), &dst); + options.enable_minification)); + v.push_str("initSearch(searchIndex);addSearchOptions(searchIndex);"); cx.shared.fs.write(&dst, &v)?; } if options.enable_index_page { @@ -1247,19 +1241,18 @@ themePicker.onblur = handleThemeButtonsBlur; // identically even with rustdoc running in parallel. all_implementors.sort(); - let mut v = Vec::new(); - try_err!(writeln!(&mut v, "(function() {{var implementors = {{}};"), &mydst); + let mut v = String::from("(function() {var implementors = {}};\n"); for implementor in &all_implementors { - try_err!(writeln!(&mut v, "{}", *implementor), &mydst); + v.push_str(&format!("{}", *implementor)); } - try_err!(writeln!(&mut v, "{}", r" + v.push_str(r" if (window.register_implementors) { window.register_implementors(implementors); } else { window.pending_implementors = implementors; } - "), &mydst); - try_err!(writeln!(&mut v, r"}})()"), &mydst); + \n"); + v.push_str("})()"); cx.shared.fs.write(&mydst, &v)?; } Ok(()) @@ -1279,68 +1272,65 @@ fn write_minify(fs:&DocFS, dst: PathBuf, contents: &str, enable_minification: bo } } -fn write_minify_replacer( - dst: &mut W, +fn minify_replacer( contents: &str, enable_minification: bool, -) -> io::Result<()> { +) -> String { use minifier::js::{simple_minify, Keyword, ReservedChar, Token, Tokens}; if enable_minification { - writeln!(dst, "{}", - { - let tokens: Tokens<'_> = simple_minify(contents) - .into_iter() - .filter(|(f, next)| { - // We keep backlines. - minifier::js::clean_token_except(f, next, &|c: &Token<'_>| { - c.get_char() != Some(ReservedChar::Backline) - }) - }) - .map(|(f, _)| { - minifier::js::replace_token_with(f, &|t: &Token<'_>| { - match *t { - Token::Keyword(Keyword::Null) => Some(Token::Other("N")), - Token::String(s) => { - let s = &s[1..s.len() -1]; // The quotes are included - if s.is_empty() { - Some(Token::Other("E")) - } else if s == "t" { - Some(Token::Other("T")) - } else if s == "u" { - Some(Token::Other("U")) - } else { - None - } - } - _ => None, - } - }) - }) - .collect::>() - .into(); - tokens.apply(|f| { - // We add a backline after the newly created variables. - minifier::js::aggregate_strings_into_array_with_separation_filter( - f, - "R", - Token::Char(ReservedChar::Backline), - // This closure prevents crates' names from being aggregated. - // - // The point here is to check if the string is preceded by '[' and - // "searchIndex". If so, it means this is a crate name and that it - // shouldn't be aggregated. - |tokens, pos| { - pos < 2 || - !tokens[pos - 1].eq_char(ReservedChar::OpenBracket) || - tokens[pos - 2].get_other() != Some("searchIndex") + let tokens: Tokens<'_> = simple_minify(contents) + .into_iter() + .filter(|(f, next)| { + // We keep backlines. + minifier::js::clean_token_except(f, next, &|c: &Token<'_>| { + c.get_char() != Some(ReservedChar::Backline) + }) + }) + .map(|(f, _)| { + minifier::js::replace_token_with(f, &|t: &Token<'_>| { + match *t { + Token::Keyword(Keyword::Null) => Some(Token::Other("N")), + Token::String(s) => { + let s = &s[1..s.len() -1]; // The quotes are included + if s.is_empty() { + Some(Token::Other("E")) + } else if s == "t" { + Some(Token::Other("T")) + } else if s == "u" { + Some(Token::Other("U")) + } else { + None } - ) - }) - .to_string() + } + _ => None, + } }) + }) + .collect::>() + .into(); + let o = tokens.apply(|f| { + // We add a backline after the newly created variables. + minifier::js::aggregate_strings_into_array_with_separation_filter( + f, + "R", + Token::Char(ReservedChar::Backline), + // This closure prevents crates' names from being aggregated. + // + // The point here is to check if the string is preceded by '[' and + // "searchIndex". If so, it means this is a crate name and that it + // shouldn't be aggregated. + |tokens, pos| { + pos < 2 || + !tokens[pos - 1].eq_char(ReservedChar::OpenBracket) || + tokens[pos - 2].get_other() != Some("searchIndex") + } + ) + }) + .to_string(); + format!("{}\n", o) } else { - writeln!(dst, "{}", contents) + format!("{}\n", contents) } } @@ -2073,9 +2063,7 @@ impl Context { if !self.render_redirect_pages { let items = self.build_sidebar_items(&m); let js_dst = self.dst.join("sidebar-items.js"); - let mut v = Vec::new(); - try_err!(write!(&mut v, "initSidebarItems({});", - as_json(&items)), &js_dst); + let v = format!("initSidebarItems({});", as_json(&items)); scx.fs.write(&js_dst, &v)?; } From 04dc72eeef1ecea0833ce022dde0fd45c4744757 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sat, 31 Aug 2019 08:52:04 -0400 Subject: [PATCH 07/17] Remove unnecessary Buffer in layout::render --- src/librustdoc/html/layout.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index cf55b9ad34308..c7b6684fd3110 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -3,7 +3,6 @@ use std::path::PathBuf; use crate::externalfiles::ExternalHtml; use crate::html::render::SlashChecker; -use crate::html::format::Buffer; #[derive(Clone)] pub struct Layout { @@ -38,10 +37,8 @@ pub fn render( t: &T, themes: &[PathBuf], ) -> String { - let mut dst = Buffer::html(); let static_root_path = page.static_root_path.unwrap_or(page.root_path); - write!(dst, -"\ + format!("\ \ \ \ @@ -239,8 +236,7 @@ pub fn render( } else { "" }, - ); - dst.into_inner() + ) } pub fn redirect(url: &str) -> String { From f8bccb1658dce1b70e08c7c8f438b65f6f9bc139 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sat, 31 Aug 2019 09:07:29 -0400 Subject: [PATCH 08/17] Move sidebar to Buffer-printing --- src/librustdoc/html/format.rs | 23 ++++++++ src/librustdoc/html/layout.rs | 5 +- src/librustdoc/html/render.rs | 104 ++++++++++++++-------------------- 3 files changed, 70 insertions(+), 62 deletions(-) diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 941d2c4acb1a8..99ddbcd7170d7 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -22,6 +22,24 @@ pub trait Print { fn print(&self, buffer: &mut Buffer); } +impl Print for &'_ T { + fn print(&self, buffer: &mut Buffer) { + (&**self).print(buffer) + } +} + +impl Print for String { + fn print(&self, buffer: &mut Buffer) { + buffer.write_str(self); + } +} + +impl Print for str { + fn print(&self, buffer: &mut Buffer) { + buffer.write_str(self); + } +} + #[derive(Debug, Clone)] pub struct Buffer { for_html: bool, @@ -74,6 +92,11 @@ impl Buffer { self.buffer.write_fmt(v).unwrap(); } + crate fn to_display(mut self, t: &T) -> String { + t.print(&mut self); + self.into_inner() + } + crate fn display(&mut self, t: T) { if self.for_html { write!(self, "{}", t); diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index c7b6684fd3110..38dcfbfcec49c 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -3,6 +3,7 @@ use std::path::PathBuf; use crate::externalfiles::ExternalHtml; use crate::html::render::SlashChecker; +use crate::html::format::{Buffer, Print}; #[derive(Clone)] pub struct Layout { @@ -30,7 +31,7 @@ pub struct Page<'a> { pub static_extra_scripts: &'a [&'a str], } -pub fn render( +pub fn render( layout: &Layout, page: &Page<'_>, sidebar: &S, @@ -208,7 +209,7 @@ pub fn render( in_header = layout.external_html.in_header, before_content = layout.external_html.before_content, after_content = layout.external_html.after_content, - sidebar = *sidebar, + sidebar = Buffer::html().to_display(sidebar), krate = layout.krate, themes = themes.iter() .filter_map(|t| t.file_stem()) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 09c2e31b4ed6b..40e7081c57c72 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -65,7 +65,7 @@ use crate::docfs::{DocFS, ErrorStorage, PathError}; use crate::doctree; use crate::fold::DocFolder; use crate::html::escape::Escape; -use crate::html::format::{Buffer, AsyncSpace, ConstnessSpace}; +use crate::html::format::{Print, Buffer, AsyncSpace, ConstnessSpace}; use crate::html::format::{GenericBounds, WhereClause, href, AbiSpace, DefaultSpace}; use crate::html::format::{VisSpace, Function, UnsafetySpace, MutableSpace}; use crate::html::format::fmt_impl_for_trait_page; @@ -4266,15 +4266,15 @@ fn item_foreign_type(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item) render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All) } -impl<'a> fmt::Display for Sidebar<'a> { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { +impl Print for Sidebar<'_> { + fn print(&self, buffer: &mut Buffer) { let cx = self.cx; let it = self.item; let parentlen = cx.current.len() - if it.is_mod() {1} else {0}; if it.is_struct() || it.is_trait() || it.is_primitive() || it.is_union() || it.is_enum() || it.is_mod() || it.is_typedef() { - write!(fmt, "

{}{}

", + write!(buffer, "

{}{}

", match it.inner { clean::StructItem(..) => "Struct ", clean::TraitItem(..) => "Trait ", @@ -4290,33 +4290,33 @@ impl<'a> fmt::Display for Sidebar<'a> { }, _ => "", }, - it.name.as_ref().unwrap())?; + it.name.as_ref().unwrap()); } if it.is_crate() { if let Some(ref version) = cache().crate_version { - write!(fmt, + write!(buffer, "
\

Version {}

\
", - version)?; + version); } } - write!(fmt, "
")?; + write!(buffer, "
"); if it.is_crate() { - write!(fmt, "

See all {}'s items

", - it.name.as_ref().expect("crates always have a name"))?; + write!(buffer, "

See all {}'s items

", + it.name.as_ref().expect("crates always have a name")); } match it.inner { - clean::StructItem(ref s) => sidebar_struct(fmt, it, s)?, - clean::TraitItem(ref t) => sidebar_trait(fmt, it, t)?, - clean::PrimitiveItem(ref p) => sidebar_primitive(fmt, it, p)?, - clean::UnionItem(ref u) => sidebar_union(fmt, it, u)?, - clean::EnumItem(ref e) => sidebar_enum(fmt, it, e)?, - clean::TypedefItem(ref t, _) => sidebar_typedef(fmt, it, t)?, - clean::ModuleItem(ref m) => sidebar_module(fmt, it, &m.items)?, - clean::ForeignTypeItem => sidebar_foreign_type(fmt, it)?, + clean::StructItem(ref s) => sidebar_struct(buffer, it, s), + clean::TraitItem(ref t) => sidebar_trait(buffer, it, t), + clean::PrimitiveItem(ref p) => sidebar_primitive(buffer, it, p), + clean::UnionItem(ref u) => sidebar_union(buffer, it, u), + clean::EnumItem(ref e) => sidebar_enum(buffer, it, e), + clean::TypedefItem(ref t, _) => sidebar_typedef(buffer, it, t), + clean::ModuleItem(ref m) => sidebar_module(buffer, it, &m.items), + clean::ForeignTypeItem => sidebar_foreign_type(buffer, it), _ => (), } @@ -4328,20 +4328,20 @@ impl<'a> fmt::Display for Sidebar<'a> { // as much HTML as possible in order to allow non-JS-enabled browsers // to navigate the documentation (though slightly inefficiently). - write!(fmt, "

")?; + write!(buffer, "

"); for (i, name) in cx.current.iter().take(parentlen).enumerate() { if i > 0 { - write!(fmt, "::")?; + write!(buffer, "::"); } - write!(fmt, "{}", + write!(buffer, "{}", &cx.root_path()[..(cx.current.len() - i - 1) * 3], - *name)?; + *name); } - write!(fmt, "

")?; + write!(buffer, "

"); // Sidebar refers to the enclosing module, not this module. let relpath = if it.is_mod() { "../" } else { "" }; - write!(fmt, + write!(buffer, "", name = it.name.as_ref().map(|x| &x[..]).unwrap_or(""), ty = it.type_().css_class(), - path = relpath)?; + path = relpath); if parentlen == 0 { // There is no sidebar-items.js beyond the crate root path // FIXME maybe dynamic crate loading can be merged here } else { - write!(fmt, "", - path = relpath)?; + write!(buffer, "", + path = relpath); } // Closes sidebar-elems div. - write!(fmt, "
")?; - - Ok(()) + write!(buffer, "
"); } } @@ -4534,8 +4532,7 @@ fn sidebar_assoc_items(it: &clean::Item) -> String { out } -fn sidebar_struct(fmt: &mut fmt::Formatter<'_>, it: &clean::Item, - s: &clean::Struct) -> fmt::Result { +fn sidebar_struct(buf: &mut Buffer, it: &clean::Item, s: &clean::Struct) { let mut sidebar = String::new(); let fields = get_struct_fields_name(&s.fields); @@ -4549,9 +4546,8 @@ fn sidebar_struct(fmt: &mut fmt::Formatter<'_>, it: &clean::Item, sidebar.push_str(&sidebar_assoc_items(it)); if !sidebar.is_empty() { - write!(fmt, "
{}
", sidebar)?; + write!(buf, "
{}
", sidebar); } - Ok(()) } fn get_id_for_impl_on_foreign_type(for_: &clean::Type, trait_: &clean::Type) -> String { @@ -4575,8 +4571,7 @@ fn is_negative_impl(i: &clean::Impl) -> bool { i.polarity == Some(clean::ImplPolarity::Negative) } -fn sidebar_trait(fmt: &mut fmt::Formatter<'_>, it: &clean::Item, - t: &clean::Trait) -> fmt::Result { +fn sidebar_trait(buf: &mut Buffer, it: &clean::Item, t: &clean::Trait) { let mut sidebar = String::new(); let types = t.items @@ -4684,27 +4679,23 @@ fn sidebar_trait(fmt: &mut fmt::Formatter<'_>, it: &clean::Item, sidebar.push_str(&sidebar_assoc_items(it)); - write!(fmt, "
{}
", sidebar) + write!(buf, "
{}
", sidebar) } -fn sidebar_primitive(fmt: &mut fmt::Formatter<'_>, it: &clean::Item, - _p: &clean::PrimitiveType) -> fmt::Result { +fn sidebar_primitive(buf: &mut Buffer, it: &clean::Item, _p: &clean::PrimitiveType) { let sidebar = sidebar_assoc_items(it); if !sidebar.is_empty() { - write!(fmt, "
{}
", sidebar)?; + write!(buf, "
{}
", sidebar); } - Ok(()) } -fn sidebar_typedef(fmt: &mut fmt::Formatter<'_>, it: &clean::Item, - _t: &clean::Typedef) -> fmt::Result { +fn sidebar_typedef(buf: &mut Buffer, it: &clean::Item, _t: &clean::Typedef) { let sidebar = sidebar_assoc_items(it); if !sidebar.is_empty() { - write!(fmt, "
{}
", sidebar)?; + write!(buf, "
{}
", sidebar); } - Ok(()) } fn get_struct_fields_name(fields: &[clean::Item]) -> String { @@ -4722,8 +4713,7 @@ fn get_struct_fields_name(fields: &[clean::Item]) -> String { .collect() } -fn sidebar_union(fmt: &mut fmt::Formatter<'_>, it: &clean::Item, - u: &clean::Union) -> fmt::Result { +fn sidebar_union(buf: &mut Buffer, it: &clean::Item, u: &clean::Union) { let mut sidebar = String::new(); let fields = get_struct_fields_name(&u.fields); @@ -4735,13 +4725,11 @@ fn sidebar_union(fmt: &mut fmt::Formatter<'_>, it: &clean::Item, sidebar.push_str(&sidebar_assoc_items(it)); if !sidebar.is_empty() { - write!(fmt, "
{}
", sidebar)?; + write!(buf, "
{}
", sidebar); } - Ok(()) } -fn sidebar_enum(fmt: &mut fmt::Formatter<'_>, it: &clean::Item, - e: &clean::Enum) -> fmt::Result { +fn sidebar_enum(buf: &mut Buffer, it: &clean::Item, e: &clean::Enum) { let mut sidebar = String::new(); let variants = e.variants.iter() @@ -4759,9 +4747,8 @@ fn sidebar_enum(fmt: &mut fmt::Formatter<'_>, it: &clean::Item, sidebar.push_str(&sidebar_assoc_items(it)); if !sidebar.is_empty() { - write!(fmt, "
{}
", sidebar)?; + write!(buf, "
{}
", sidebar); } - Ok(()) } fn item_ty_to_strs(ty: &ItemType) -> (&'static str, &'static str) { @@ -4795,8 +4782,7 @@ fn item_ty_to_strs(ty: &ItemType) -> (&'static str, &'static str) { } } -fn sidebar_module(fmt: &mut fmt::Formatter<'_>, _it: &clean::Item, - items: &[clean::Item]) -> fmt::Result { +fn sidebar_module(buf: &mut Buffer, _it: &clean::Item, items: &[clean::Item]) { let mut sidebar = String::new(); if items.iter().any(|it| it.type_() == ItemType::ExternCrate || @@ -4823,17 +4809,15 @@ fn sidebar_module(fmt: &mut fmt::Formatter<'_>, _it: &clean::Item, } if !sidebar.is_empty() { - write!(fmt, "
    {}
", sidebar)?; + write!(buf, "
    {}
", sidebar); } - Ok(()) } -fn sidebar_foreign_type(fmt: &mut fmt::Formatter<'_>, it: &clean::Item) -> fmt::Result { +fn sidebar_foreign_type(buf: &mut Buffer, it: &clean::Item) { let sidebar = sidebar_assoc_items(it); if !sidebar.is_empty() { - write!(fmt, "
{}
", sidebar)?; + write!(buf, "
{}
", sidebar); } - Ok(()) } fn item_macro(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item, From f4a15ae3b248bf91f10f6e5d031ca84dc1942e19 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sat, 31 Aug 2019 11:22:51 -0400 Subject: [PATCH 09/17] Implement Print for FnOnce(&mut Buffer) This means that callers can pass in a closure like `|buf| some_function(..., &mut buf)` and pass in arbitrary arguments to that function without complicating the trait definition. We also keep the impl for str and String, since it's useful to be able to just pass in "" or format!("{}"...) results in some cases. This changes Print's definition to take self, instead of &self, because otherwise FnOnce cannot be called directly. We could instead take FnMut or even Fn, but that seems like it'd merely complicate matters -- most of the time, the FnOnce does not constrain us at all anyway. If it does, a custom Print impl for &'_ SomeStruct is not all that painful. --- src/librustdoc/html/format.rs | 20 +++++++++++--------- src/librustdoc/html/layout.rs | 2 +- src/librustdoc/html/render.rs | 10 +++++----- src/librustdoc/html/sources.rs | 2 +- 4 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 99ddbcd7170d7..5d86f0566111f 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -19,23 +19,25 @@ use crate::html::item_type::ItemType; use crate::html::render::{self, cache, CURRENT_DEPTH}; pub trait Print { - fn print(&self, buffer: &mut Buffer); + fn print(self, buffer: &mut Buffer); } -impl Print for &'_ T { - fn print(&self, buffer: &mut Buffer) { - (&**self).print(buffer) +impl Print for F + where F: FnOnce(&mut Buffer), +{ + fn print(self, buffer: &mut Buffer) { + (self)(buffer) } } impl Print for String { - fn print(&self, buffer: &mut Buffer) { - buffer.write_str(self); + fn print(self, buffer: &mut Buffer) { + buffer.write_str(&self); } } -impl Print for str { - fn print(&self, buffer: &mut Buffer) { +impl Print for &'_ str { + fn print(self, buffer: &mut Buffer) { buffer.write_str(self); } } @@ -92,7 +94,7 @@ impl Buffer { self.buffer.write_fmt(v).unwrap(); } - crate fn to_display(mut self, t: &T) -> String { + crate fn to_display(mut self, t: T) -> String { t.print(&mut self); self.into_inner() } diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index 38dcfbfcec49c..1202f411f912c 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -34,7 +34,7 @@ pub struct Page<'a> { pub fn render( layout: &Layout, page: &Page<'_>, - sidebar: &S, + sidebar: S, t: &T, themes: &[PathBuf], ) -> String { diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 40e7081c57c72..fc7038f8bda96 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1174,7 +1174,7 @@ themePicker.onblur = handleThemeButtonsBlur; }) .collect::()); let v = layout::render(&cx.shared.layout, - &page, &(""), &content, + &page, "", &content, &cx.shared.themes); cx.shared.fs.write(&dst, v.as_bytes())?; } @@ -1921,7 +1921,7 @@ impl Context { String::new() }; let v = layout::render(&self.shared.layout, - &page, &sidebar, &all, + &page, sidebar, &all, &self.shared.themes); self.shared.fs.write(&final_file, v.as_bytes())?; @@ -1937,7 +1937,7 @@ impl Context { themes.push(PathBuf::from("settings.css")); let v = layout::render( &self.shared.layout, - &page, &sidebar, &settings, + &page, sidebar, &settings, &themes); self.shared.fs.write(&settings_file, v.as_bytes())?; @@ -1994,7 +1994,7 @@ impl Context { if !self.render_redirect_pages { layout::render(&self.shared.layout, &page, - &Sidebar{ cx: self, item: it }, + Sidebar{ cx: self, item: it }, &Item{ cx: self, item: it }, &self.shared.themes) } else { @@ -4267,7 +4267,7 @@ fn item_foreign_type(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item) } impl Print for Sidebar<'_> { - fn print(&self, buffer: &mut Buffer) { + fn print(self, buffer: &mut Buffer) { let cx = self.cx; let it = self.item; let parentlen = cx.current.len() - if it.is_mod() {1} else {0}; diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs index 018db3f9363cb..94ae14226097f 100644 --- a/src/librustdoc/html/sources.rs +++ b/src/librustdoc/html/sources.rs @@ -120,7 +120,7 @@ impl<'a> SourceCollector<'a> { static_extra_scripts: &[&format!("source-script{}", self.scx.resource_suffix)], }; let v = layout::render(&self.scx.layout, - &page, &(""), &Source(contents), + &page, "", &Source(contents), &self.scx.themes); self.scx.fs.write(&cur, v.as_bytes())?; self.scx.local_sources.insert(p.clone(), href); From eefaee1af4cc3df09d2588638c2bb250fe6a30e6 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sat, 31 Aug 2019 11:32:47 -0400 Subject: [PATCH 10/17] Delete Sidebar struct in favor of FnOnce impl --- src/librustdoc/html/render.rs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index fc7038f8bda96..3dec5c2a20e8e 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -387,8 +387,6 @@ struct Item<'a> { item: &'a clean::Item, } -struct Sidebar<'a> { cx: &'a Context, item: &'a clean::Item, } - /// Struct representing one entry in the JS search index. These are all emitted /// by hand to a large JS file at the end of cache-creation. #[derive(Debug)] @@ -1994,7 +1992,7 @@ impl Context { if !self.render_redirect_pages { layout::render(&self.shared.layout, &page, - Sidebar{ cx: self, item: it }, + |buf: &mut _| print_sidebar(self, it, buf), &Item{ cx: self, item: it }, &self.shared.themes) } else { @@ -4266,10 +4264,7 @@ fn item_foreign_type(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item) render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All) } -impl Print for Sidebar<'_> { - fn print(self, buffer: &mut Buffer) { - let cx = self.cx; - let it = self.item; + fn print_sidebar(cx: &Context, it: &clean::Item, buffer: &mut Buffer) { let parentlen = cx.current.len() - if it.is_mod() {1} else {0}; if it.is_struct() || it.is_trait() || it.is_primitive() || it.is_union() @@ -4360,7 +4355,6 @@ impl Print for Sidebar<'_> { // Closes sidebar-elems div. write!(buffer, ""); } -} fn get_next_url(used_links: &mut FxHashSet, url: String) -> String { if used_links.insert(url.clone()) { From d5f147086bbc70eb248804d3a16c643979fd1f2b Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sat, 31 Aug 2019 11:34:37 -0400 Subject: [PATCH 11/17] De-indent all fmt::Display impls for later replacement to functions --- src/librustdoc/html/format.rs | 10 +- src/librustdoc/html/render.rs | 466 ++++++++++++++++----------------- src/librustdoc/html/sources.rs | 34 +-- 3 files changed, 255 insertions(+), 255 deletions(-) diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 5d86f0566111f..f3c40c8568bb6 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -290,11 +290,11 @@ impl<'a> fmt::Display for WhereClause<'a> { } &clean::WherePredicate::RegionPredicate { ref lifetime, ref bounds } => { clause.push_str(&format!("{}: {}", - lifetime, - bounds.iter() - .map(|b| b.to_string()) - .collect::>() - .join(" + "))); + lifetime, + bounds.iter() + .map(|b| b.to_string()) + .collect::>() + .join(" + "))); } &clean::WherePredicate::EqPredicate { ref lhs, ref rhs } => { if f.alternate() { diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 3dec5c2a20e8e..1d1e54fc9eaba 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1772,33 +1772,33 @@ fn print_entries(f: &mut fmt::Formatter<'_>, e: &FxHashSet, title: &s } impl fmt::Display for AllTypes { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, +fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "

\ - \ - \ - \ - []\ - \ - - - List of all items\ + \ + \ + \ + []\ + \ + + + List of all items\

")?; - print_entries(f, &self.structs, "Structs", "structs")?; - print_entries(f, &self.enums, "Enums", "enums")?; - print_entries(f, &self.unions, "Unions", "unions")?; - print_entries(f, &self.primitives, "Primitives", "primitives")?; - print_entries(f, &self.traits, "Traits", "traits")?; - print_entries(f, &self.macros, "Macros", "macros")?; - print_entries(f, &self.attributes, "Attribute Macros", "attributes")?; - print_entries(f, &self.derives, "Derive Macros", "derives")?; - print_entries(f, &self.functions, "Functions", "functions")?; - print_entries(f, &self.typedefs, "Typedefs", "typedefs")?; - print_entries(f, &self.trait_aliases, "Trait Aliases", "trait-aliases")?; - print_entries(f, &self.opaque_tys, "Opaque Types", "opaque-types")?; - print_entries(f, &self.statics, "Statics", "statics")?; - print_entries(f, &self.constants, "Constants", "constants") - } + print_entries(f, &self.structs, "Structs", "structs")?; + print_entries(f, &self.enums, "Enums", "enums")?; + print_entries(f, &self.unions, "Unions", "unions")?; + print_entries(f, &self.primitives, "Primitives", "primitives")?; + print_entries(f, &self.traits, "Traits", "traits")?; + print_entries(f, &self.macros, "Macros", "macros")?; + print_entries(f, &self.attributes, "Attribute Macros", "attributes")?; + print_entries(f, &self.derives, "Derive Macros", "derives")?; + print_entries(f, &self.functions, "Functions", "functions")?; + print_entries(f, &self.typedefs, "Typedefs", "typedefs")?; + print_entries(f, &self.trait_aliases, "Trait Aliases", "trait-aliases")?; + print_entries(f, &self.opaque_tys, "Opaque Types", "opaque-types")?; + print_entries(f, &self.statics, "Statics", "statics")?; + print_entries(f, &self.constants, "Constants", "constants") +} } #[derive(Debug)] @@ -1829,27 +1829,27 @@ impl<'a> Settings<'a> { } impl<'a> fmt::Display for Settings<'a> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, +fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "

\ - Rustdoc settings\ + Rustdoc settings\

\
{}
\ ", - self.settings.iter() - .map(|(id, text, enabled)| { - format!("
\ - \ -
{}
\ -
", id, if *enabled { " checked" } else { "" }, text) - }) - .collect::(), - self.root_path, - self.suffix) - } + self.settings.iter() + .map(|(id, text, enabled)| { + format!("
\ + \ +
{}
\ +
", id, if *enabled { " checked" } else { "" }, text) + }) + .collect::(), + self.root_path, + self.suffix) +} } impl Context { @@ -2205,108 +2205,108 @@ where F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result { } impl<'a> fmt::Display for Item<'a> { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - debug_assert!(!self.item.is_stripped()); - // Write the breadcrumb trail header for the top - write!(fmt, "

")?; - if let Some(version) = self.item.stable_since() { - write!(fmt, "{0}", - version)?; - } - write!(fmt, - "\ - \ - []\ - \ - ")?; - - // Write `src` tag - // - // When this item is part of a `pub use` in a downstream crate, the - // [src] link in the downstream documentation will actually come back to - // this page, and this link will be auto-clicked. The `id` attribute is - // used to find the link to auto-click. - if self.cx.shared.include_sources && !self.item.is_primitive() { - if let Some(l) = self.src_href() { - write!(fmt, "[src]", - l, "goto source code")?; - } - } - - write!(fmt, "")?; // out-of-band - write!(fmt, "")?; - match self.item.inner { - clean::ModuleItem(ref m) => if m.is_crate { - write!(fmt, "Crate ")?; - } else { - write!(fmt, "Module ")?; - }, - clean::FunctionItem(..) | clean::ForeignFunctionItem(..) => write!(fmt, "Function ")?, - clean::TraitItem(..) => write!(fmt, "Trait ")?, - clean::StructItem(..) => write!(fmt, "Struct ")?, - clean::UnionItem(..) => write!(fmt, "Union ")?, - clean::EnumItem(..) => write!(fmt, "Enum ")?, - clean::TypedefItem(..) => write!(fmt, "Type Definition ")?, - clean::MacroItem(..) => write!(fmt, "Macro ")?, - clean::ProcMacroItem(ref mac) => match mac.kind { - MacroKind::Bang => write!(fmt, "Macro ")?, - MacroKind::Attr => write!(fmt, "Attribute Macro ")?, - MacroKind::Derive => write!(fmt, "Derive Macro ")?, - } - clean::PrimitiveItem(..) => write!(fmt, "Primitive Type ")?, - clean::StaticItem(..) | clean::ForeignStaticItem(..) => write!(fmt, "Static ")?, - clean::ConstantItem(..) => write!(fmt, "Constant ")?, - clean::ForeignTypeItem => write!(fmt, "Foreign Type ")?, - clean::KeywordItem(..) => write!(fmt, "Keyword ")?, - clean::OpaqueTyItem(..) => write!(fmt, "Opaque Type ")?, - clean::TraitAliasItem(..) => write!(fmt, "Trait Alias ")?, - _ => { - // We don't generate pages for any other type. - unreachable!(); - } - } - if !self.item.is_primitive() && !self.item.is_keyword() { - let cur = &self.cx.current; - let amt = if self.item.is_mod() { cur.len() - 1 } else { cur.len() }; - for (i, component) in cur.iter().enumerate().take(amt) { - write!(fmt, "{}::", - "../".repeat(cur.len() - i - 1), - component)?; - } - } - write!(fmt, "{}", - self.item.type_(), self.item.name.as_ref().unwrap())?; - - write!(fmt, "

")?; // in-band - - match self.item.inner { - clean::ModuleItem(ref m) => - item_module(fmt, self.cx, self.item, &m.items), - clean::FunctionItem(ref f) | clean::ForeignFunctionItem(ref f) => - item_function(fmt, self.cx, self.item, f), - clean::TraitItem(ref t) => item_trait(fmt, self.cx, self.item, t), - clean::StructItem(ref s) => item_struct(fmt, self.cx, self.item, s), - clean::UnionItem(ref s) => item_union(fmt, self.cx, self.item, s), - clean::EnumItem(ref e) => item_enum(fmt, self.cx, self.item, e), - clean::TypedefItem(ref t, _) => item_typedef(fmt, self.cx, self.item, t), - clean::MacroItem(ref m) => item_macro(fmt, self.cx, self.item, m), - clean::ProcMacroItem(ref m) => item_proc_macro(fmt, self.cx, self.item, m), - clean::PrimitiveItem(ref p) => item_primitive(fmt, self.cx, self.item, p), - clean::StaticItem(ref i) | clean::ForeignStaticItem(ref i) => - item_static(fmt, self.cx, self.item, i), - clean::ConstantItem(ref c) => item_constant(fmt, self.cx, self.item, c), - clean::ForeignTypeItem => item_foreign_type(fmt, self.cx, self.item), - clean::KeywordItem(ref k) => item_keyword(fmt, self.cx, self.item, k), - clean::OpaqueTyItem(ref e, _) => item_opaque_ty(fmt, self.cx, self.item, e), - clean::TraitAliasItem(ref ta) => item_trait_alias(fmt, self.cx, self.item, ta), - _ => { - // We don't generate pages for any other type. - unreachable!(); - } +fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + debug_assert!(!self.item.is_stripped()); + // Write the breadcrumb trail header for the top + write!(fmt, "

")?; + if let Some(version) = self.item.stable_since() { + write!(fmt, "{0}", + version)?; + } + write!(fmt, + "\ + \ + []\ + \ + ")?; + + // Write `src` tag + // + // When this item is part of a `pub use` in a downstream crate, the + // [src] link in the downstream documentation will actually come back to + // this page, and this link will be auto-clicked. The `id` attribute is + // used to find the link to auto-click. + if self.cx.shared.include_sources && !self.item.is_primitive() { + if let Some(l) = self.src_href() { + write!(fmt, "[src]", + l, "goto source code")?; + } + } + + write!(fmt, "")?; // out-of-band + write!(fmt, "")?; + match self.item.inner { + clean::ModuleItem(ref m) => if m.is_crate { + write!(fmt, "Crate ")?; + } else { + write!(fmt, "Module ")?; + }, + clean::FunctionItem(..) | clean::ForeignFunctionItem(..) => write!(fmt, "Function ")?, + clean::TraitItem(..) => write!(fmt, "Trait ")?, + clean::StructItem(..) => write!(fmt, "Struct ")?, + clean::UnionItem(..) => write!(fmt, "Union ")?, + clean::EnumItem(..) => write!(fmt, "Enum ")?, + clean::TypedefItem(..) => write!(fmt, "Type Definition ")?, + clean::MacroItem(..) => write!(fmt, "Macro ")?, + clean::ProcMacroItem(ref mac) => match mac.kind { + MacroKind::Bang => write!(fmt, "Macro ")?, + MacroKind::Attr => write!(fmt, "Attribute Macro ")?, + MacroKind::Derive => write!(fmt, "Derive Macro ")?, + } + clean::PrimitiveItem(..) => write!(fmt, "Primitive Type ")?, + clean::StaticItem(..) | clean::ForeignStaticItem(..) => write!(fmt, "Static ")?, + clean::ConstantItem(..) => write!(fmt, "Constant ")?, + clean::ForeignTypeItem => write!(fmt, "Foreign Type ")?, + clean::KeywordItem(..) => write!(fmt, "Keyword ")?, + clean::OpaqueTyItem(..) => write!(fmt, "Opaque Type ")?, + clean::TraitAliasItem(..) => write!(fmt, "Trait Alias ")?, + _ => { + // We don't generate pages for any other type. + unreachable!(); + } + } + if !self.item.is_primitive() && !self.item.is_keyword() { + let cur = &self.cx.current; + let amt = if self.item.is_mod() { cur.len() - 1 } else { cur.len() }; + for (i, component) in cur.iter().enumerate().take(amt) { + write!(fmt, "{}::", + "../".repeat(cur.len() - i - 1), + component)?; + } + } + write!(fmt, "{}", + self.item.type_(), self.item.name.as_ref().unwrap())?; + + write!(fmt, "

")?; // in-band + + match self.item.inner { + clean::ModuleItem(ref m) => + item_module(fmt, self.cx, self.item, &m.items), + clean::FunctionItem(ref f) | clean::ForeignFunctionItem(ref f) => + item_function(fmt, self.cx, self.item, f), + clean::TraitItem(ref t) => item_trait(fmt, self.cx, self.item, t), + clean::StructItem(ref s) => item_struct(fmt, self.cx, self.item, s), + clean::UnionItem(ref s) => item_union(fmt, self.cx, self.item, s), + clean::EnumItem(ref e) => item_enum(fmt, self.cx, self.item, e), + clean::TypedefItem(ref t, _) => item_typedef(fmt, self.cx, self.item, t), + clean::MacroItem(ref m) => item_macro(fmt, self.cx, self.item, m), + clean::ProcMacroItem(ref m) => item_proc_macro(fmt, self.cx, self.item, m), + clean::PrimitiveItem(ref p) => item_primitive(fmt, self.cx, self.item, p), + clean::StaticItem(ref i) | clean::ForeignStaticItem(ref i) => + item_static(fmt, self.cx, self.item, i), + clean::ConstantItem(ref c) => item_constant(fmt, self.cx, self.item, c), + clean::ForeignTypeItem => item_foreign_type(fmt, self.cx, self.item), + clean::KeywordItem(ref k) => item_keyword(fmt, self.cx, self.item, k), + clean::OpaqueTyItem(ref e, _) => item_opaque_ty(fmt, self.cx, self.item, e), + clean::TraitAliasItem(ref ta) => item_trait_alias(fmt, self.cx, self.item, ta), + _ => { + // We don't generate pages for any other type. + unreachable!(); } } } +} fn item_path(ty: ItemType, name: &str) -> String { match ty { @@ -3834,9 +3834,9 @@ fn render_assoc_items(w: &mut fmt::Formatter<'_>, struct RendererStruct<'a, 'b, 'c>(&'a Context, Vec<&'b &'b Impl>, &'c clean::Item); impl<'a, 'b, 'c> fmt::Display for RendererStruct<'a, 'b, 'c> { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - render_impls(self.0, fmt, &self.1, self.2) - } + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + render_impls(self.0, fmt, &self.1, self.2) + } } let impls = RendererStruct(cx, concrete, containing_item).to_string(); @@ -4264,97 +4264,97 @@ fn item_foreign_type(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item) render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All) } - fn print_sidebar(cx: &Context, it: &clean::Item, buffer: &mut Buffer) { - let parentlen = cx.current.len() - if it.is_mod() {1} else {0}; - - if it.is_struct() || it.is_trait() || it.is_primitive() || it.is_union() - || it.is_enum() || it.is_mod() || it.is_typedef() { - write!(buffer, "

{}{}

", - match it.inner { - clean::StructItem(..) => "Struct ", - clean::TraitItem(..) => "Trait ", - clean::PrimitiveItem(..) => "Primitive Type ", - clean::UnionItem(..) => "Union ", - clean::EnumItem(..) => "Enum ", - clean::TypedefItem(..) => "Type Definition ", - clean::ForeignTypeItem => "Foreign Type ", - clean::ModuleItem(..) => if it.is_crate() { - "Crate " - } else { - "Module " - }, - _ => "", +fn print_sidebar(cx: &Context, it: &clean::Item, buffer: &mut Buffer) { + let parentlen = cx.current.len() - if it.is_mod() {1} else {0}; + + if it.is_struct() || it.is_trait() || it.is_primitive() || it.is_union() + || it.is_enum() || it.is_mod() || it.is_typedef() { + write!(buffer, "

{}{}

", + match it.inner { + clean::StructItem(..) => "Struct ", + clean::TraitItem(..) => "Trait ", + clean::PrimitiveItem(..) => "Primitive Type ", + clean::UnionItem(..) => "Union ", + clean::EnumItem(..) => "Enum ", + clean::TypedefItem(..) => "Type Definition ", + clean::ForeignTypeItem => "Foreign Type ", + clean::ModuleItem(..) => if it.is_crate() { + "Crate " + } else { + "Module " }, - it.name.as_ref().unwrap()); - } - - if it.is_crate() { - if let Some(ref version) = cache().crate_version { - write!(buffer, - "
\ -

Version {}

\ -
", - version); - } - } - - write!(buffer, "
"); - if it.is_crate() { - write!(buffer, "

See all {}'s items

", - it.name.as_ref().expect("crates always have a name")); - } - match it.inner { - clean::StructItem(ref s) => sidebar_struct(buffer, it, s), - clean::TraitItem(ref t) => sidebar_trait(buffer, it, t), - clean::PrimitiveItem(ref p) => sidebar_primitive(buffer, it, p), - clean::UnionItem(ref u) => sidebar_union(buffer, it, u), - clean::EnumItem(ref e) => sidebar_enum(buffer, it, e), - clean::TypedefItem(ref t, _) => sidebar_typedef(buffer, it, t), - clean::ModuleItem(ref m) => sidebar_module(buffer, it, &m.items), - clean::ForeignTypeItem => sidebar_foreign_type(buffer, it), - _ => (), - } - - // The sidebar is designed to display sibling functions, modules and - // other miscellaneous information. since there are lots of sibling - // items (and that causes quadratic growth in large modules), - // we refactor common parts into a shared JavaScript file per module. - // still, we don't move everything into JS because we want to preserve - // as much HTML as possible in order to allow non-JS-enabled browsers - // to navigate the documentation (though slightly inefficiently). - - write!(buffer, "

"); - for (i, name) in cx.current.iter().take(parentlen).enumerate() { - if i > 0 { - write!(buffer, "::"); - } - write!(buffer, "{}", - &cx.root_path()[..(cx.current.len() - i - 1) * 3], - *name); - } - write!(buffer, "

"); - - // Sidebar refers to the enclosing module, not this module. - let relpath = if it.is_mod() { "../" } else { "" }; - write!(buffer, - "", - name = it.name.as_ref().map(|x| &x[..]).unwrap_or(""), - ty = it.type_().css_class(), - path = relpath); - if parentlen == 0 { - // There is no sidebar-items.js beyond the crate root path - // FIXME maybe dynamic crate loading can be merged here - } else { - write!(buffer, "", - path = relpath); - } - // Closes sidebar-elems div. - write!(buffer, "
"); + _ => "", + }, + it.name.as_ref().unwrap()); + } + + if it.is_crate() { + if let Some(ref version) = cache().crate_version { + write!(buffer, + "
\ +

Version {}

\ +
", + version); + } + } + + write!(buffer, "
"); + if it.is_crate() { + write!(buffer, "

See all {}'s items

", + it.name.as_ref().expect("crates always have a name")); + } + match it.inner { + clean::StructItem(ref s) => sidebar_struct(buffer, it, s), + clean::TraitItem(ref t) => sidebar_trait(buffer, it, t), + clean::PrimitiveItem(ref p) => sidebar_primitive(buffer, it, p), + clean::UnionItem(ref u) => sidebar_union(buffer, it, u), + clean::EnumItem(ref e) => sidebar_enum(buffer, it, e), + clean::TypedefItem(ref t, _) => sidebar_typedef(buffer, it, t), + clean::ModuleItem(ref m) => sidebar_module(buffer, it, &m.items), + clean::ForeignTypeItem => sidebar_foreign_type(buffer, it), + _ => (), + } + + // The sidebar is designed to display sibling functions, modules and + // other miscellaneous information. since there are lots of sibling + // items (and that causes quadratic growth in large modules), + // we refactor common parts into a shared JavaScript file per module. + // still, we don't move everything into JS because we want to preserve + // as much HTML as possible in order to allow non-JS-enabled browsers + // to navigate the documentation (though slightly inefficiently). + + write!(buffer, "

"); + for (i, name) in cx.current.iter().take(parentlen).enumerate() { + if i > 0 { + write!(buffer, "::"); + } + write!(buffer, "{}", + &cx.root_path()[..(cx.current.len() - i - 1) * 3], + *name); + } + write!(buffer, "

"); + + // Sidebar refers to the enclosing module, not this module. + let relpath = if it.is_mod() { "../" } else { "" }; + write!(buffer, + "", + name = it.name.as_ref().map(|x| &x[..]).unwrap_or(""), + ty = it.type_().css_class(), + path = relpath); + if parentlen == 0 { + // There is no sidebar-items.js beyond the crate root path + // FIXME maybe dynamic crate loading can be merged here + } else { + write!(buffer, "", + path = relpath); } + // Closes sidebar-elems div. + write!(buffer, "
"); +} fn get_next_url(used_links: &mut FxHashSet, url: String) -> String { if used_links.insert(url.clone()) { diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs index 94ae14226097f..6dccfdadf0fb8 100644 --- a/src/librustdoc/html/sources.rs +++ b/src/librustdoc/html/sources.rs @@ -160,22 +160,22 @@ where struct Source<'a>(&'a str); impl<'a> fmt::Display for Source<'a> { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - let Source(s) = *self; - let lines = s.lines().count(); - let mut cols = 0; - let mut tmp = lines; - while tmp > 0 { - cols += 1; - tmp /= 10; - } - write!(fmt, "
")?;
-        for i in 1..=lines {
-            write!(fmt, "{0:1$}\n", i, cols)?;
-        }
-        write!(fmt, "
")?; - write!(fmt, "{}", - highlight::render_with_highlighting(s, None, None, None))?; - Ok(()) +fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + let Source(s) = *self; + let lines = s.lines().count(); + let mut cols = 0; + let mut tmp = lines; + while tmp > 0 { + cols += 1; + tmp /= 10; } + write!(fmt, "
")?;
+    for i in 1..=lines {
+        write!(fmt, "{0:1$}\n", i, cols)?;
+    }
+    write!(fmt, "
")?; + write!(fmt, "{}", + highlight::render_with_highlighting(s, None, None, None))?; + Ok(()) +} } From 3f0e77f19c16eb3cd46390ab0082ad749cb1c5b5 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sat, 31 Aug 2019 12:18:25 -0400 Subject: [PATCH 12/17] layout::render takes Print instead of fmt::Display --- src/librustdoc/html/format.rs | 6 +++++- src/librustdoc/html/layout.rs | 7 +++---- src/librustdoc/html/render.rs | 10 +++++----- src/librustdoc/html/sources.rs | 3 ++- 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index f3c40c8568bb6..80f34fb17d2e8 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -99,7 +99,11 @@ impl Buffer { self.into_inner() } - crate fn display(&mut self, t: T) { + crate fn with_formatter) -> fmt::Result>(&mut self, t: T) { + self.from_display(display_fn(move |f| (t)(f))); + } + + crate fn from_display(&mut self, t: T) { if self.for_html { write!(self, "{}", t); } else { diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index 1202f411f912c..56074f4ab1192 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -1,4 +1,3 @@ -use std::fmt; use std::path::PathBuf; use crate::externalfiles::ExternalHtml; @@ -31,11 +30,11 @@ pub struct Page<'a> { pub static_extra_scripts: &'a [&'a str], } -pub fn render( +pub fn render( layout: &Layout, page: &Page<'_>, sidebar: S, - t: &T, + t: T, themes: &[PathBuf], ) -> String { let static_root_path = page.static_root_path.unwrap_or(page.root_path); @@ -175,7 +174,7 @@ pub fn render( } else { String::new() }, - content = *t, + content = Buffer::html().to_display(t), static_root_path = static_root_path, root_path = page.root_path, css_class = page.css_class, diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 1d1e54fc9eaba..4514a540f543a 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -65,7 +65,7 @@ use crate::docfs::{DocFS, ErrorStorage, PathError}; use crate::doctree; use crate::fold::DocFolder; use crate::html::escape::Escape; -use crate::html::format::{Print, Buffer, AsyncSpace, ConstnessSpace}; +use crate::html::format::{Buffer, AsyncSpace, ConstnessSpace}; use crate::html::format::{GenericBounds, WhereClause, href, AbiSpace, DefaultSpace}; use crate::html::format::{VisSpace, Function, UnsafetySpace, MutableSpace}; use crate::html::format::fmt_impl_for_trait_page; @@ -1172,7 +1172,7 @@ themePicker.onblur = handleThemeButtonsBlur; }) .collect::()); let v = layout::render(&cx.shared.layout, - &page, "", &content, + &page, "", content, &cx.shared.themes); cx.shared.fs.write(&dst, v.as_bytes())?; } @@ -1919,7 +1919,7 @@ impl Context { String::new() }; let v = layout::render(&self.shared.layout, - &page, sidebar, &all, + &page, sidebar, |buf: &mut Buffer| buf.from_display(all), &self.shared.themes); self.shared.fs.write(&final_file, v.as_bytes())?; @@ -1935,7 +1935,7 @@ impl Context { themes.push(PathBuf::from("settings.css")); let v = layout::render( &self.shared.layout, - &page, sidebar, &settings, + &page, sidebar, |buf: &mut Buffer| buf.from_display(settings), &themes); self.shared.fs.write(&settings_file, v.as_bytes())?; @@ -1993,7 +1993,7 @@ impl Context { if !self.render_redirect_pages { layout::render(&self.shared.layout, &page, |buf: &mut _| print_sidebar(self, it, buf), - &Item{ cx: self, item: it }, + |buf: &mut Buffer| buf.from_display(Item { cx: self, item: it }), &self.shared.themes) } else { let mut url = self.root_path(); diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs index 6dccfdadf0fb8..e94ae1d968ef5 100644 --- a/src/librustdoc/html/sources.rs +++ b/src/librustdoc/html/sources.rs @@ -4,6 +4,7 @@ use crate::fold::DocFolder; use crate::html::layout; use crate::html::render::{Error, SharedContext, BASIC_KEYWORDS}; use crate::html::highlight; +use crate::html::format::Buffer; use std::ffi::OsStr; use std::fs; use std::path::{Component, Path, PathBuf}; @@ -120,7 +121,7 @@ impl<'a> SourceCollector<'a> { static_extra_scripts: &[&format!("source-script{}", self.scx.resource_suffix)], }; let v = layout::render(&self.scx.layout, - &page, "", &Source(contents), + &page, "", |buf: &mut Buffer| buf.from_display(Source(&contents)), &self.scx.themes); self.scx.fs.write(&cur, v.as_bytes())?; self.scx.local_sources.insert(p.clone(), href); From bb40d5fa498603f041dcf1092099c0b93928e442 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sat, 31 Aug 2019 12:20:56 -0400 Subject: [PATCH 13/17] Move Source to Buffer --- src/librustdoc/html/sources.rs | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs index e94ae1d968ef5..d840683a7af87 100644 --- a/src/librustdoc/html/sources.rs +++ b/src/librustdoc/html/sources.rs @@ -8,7 +8,6 @@ use crate::html::format::Buffer; use std::ffi::OsStr; use std::fs; use std::path::{Component, Path, PathBuf}; -use std::fmt; use syntax::source_map::FileName; crate fn render(dst: &Path, scx: &mut SharedContext, @@ -121,7 +120,7 @@ impl<'a> SourceCollector<'a> { static_extra_scripts: &[&format!("source-script{}", self.scx.resource_suffix)], }; let v = layout::render(&self.scx.layout, - &page, "", |buf: &mut Buffer| buf.from_display(Source(&contents)), + &page, "", |buf: &mut _| print_src(buf, &contents), &self.scx.themes); self.scx.fs.write(&cur, v.as_bytes())?; self.scx.local_sources.insert(p.clone(), href); @@ -158,11 +157,7 @@ where /// Wrapper struct to render the source code of a file. This will do things like /// adding line numbers to the left-hand side. -struct Source<'a>(&'a str); - -impl<'a> fmt::Display for Source<'a> { -fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - let Source(s) = *self; +fn print_src(buf: &mut Buffer, s: &str) { let lines = s.lines().count(); let mut cols = 0; let mut tmp = lines; @@ -170,13 +165,11 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { cols += 1; tmp /= 10; } - write!(fmt, "
")?;
+    write!(buf, "
");
     for i in 1..=lines {
-        write!(fmt, "{0:1$}\n", i, cols)?;
+        write!(buf, "{0:1$}\n", i, cols);
     }
-    write!(fmt, "
")?; - write!(fmt, "{}", - highlight::render_with_highlighting(s, None, None, None))?; - Ok(()) -} + write!(buf, "
"); + write!(buf, "{}", + highlight::render_with_highlighting(s, None, None, None)); } From 17bef30d0b1cc3851fb76fdd84b4d15bb629dc39 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sat, 31 Aug 2019 12:27:27 -0400 Subject: [PATCH 14/17] Settings to function --- src/librustdoc/html/render.rs | 55 ++++++++++++----------------------- 1 file changed, 19 insertions(+), 36 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 4514a540f543a..2eb2ba4e2b201 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1801,42 +1801,25 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { } } -#[derive(Debug)] -struct Settings<'a> { +fn settings(root_path: &str, suffix: &str) -> String { // (id, explanation, default value) - settings: Vec<(&'static str, &'static str, bool)>, - root_path: &'a str, - suffix: &'a str, -} - -impl<'a> Settings<'a> { - pub fn new(root_path: &'a str, suffix: &'a str) -> Settings<'a> { - Settings { - settings: vec![ - ("item-declarations", "Auto-hide item declarations.", true), - ("item-attributes", "Auto-hide item attributes.", true), - ("trait-implementations", "Auto-hide trait implementations documentation", - true), - ("method-docs", "Auto-hide item methods' documentation", false), - ("go-to-only-result", "Directly go to item in search if there is only one result", - false), - ("line-numbers", "Show line numbers on code examples", false), - ], - root_path, - suffix, - } - } -} - -impl<'a> fmt::Display for Settings<'a> { -fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, + let settings = [ + ("item-declarations", "Auto-hide item declarations.", true), + ("item-attributes", "Auto-hide item attributes.", true), + ("trait-implementations", "Auto-hide trait implementations documentation", + true), + ("method-docs", "Auto-hide item methods' documentation", false), + ("go-to-only-result", "Directly go to item in search if there is only one result", + false), + ("line-numbers", "Show line numbers on code examples", false), + ]; + format!( "

\ Rustdoc settings\

\
{}
\ ", - self.settings.iter() + settings.iter() .map(|(id, text, enabled)| { format!("
\
", id, if *enabled { " checked" } else { "" }, text) }) .collect::(), - self.root_path, - self.suffix) -} + root_path, + suffix) } impl Context { @@ -1924,8 +1906,6 @@ impl Context { self.shared.fs.write(&final_file, v.as_bytes())?; // Generating settings page. - let settings = Settings::new(self.shared.static_root_path.as_deref().unwrap_or("./"), - &self.shared.resource_suffix); page.title = "Rustdoc settings"; page.description = "Settings of Rustdoc"; page.root_path = "./"; @@ -1935,7 +1915,10 @@ impl Context { themes.push(PathBuf::from("settings.css")); let v = layout::render( &self.shared.layout, - &page, sidebar, |buf: &mut Buffer| buf.from_display(settings), + &page, sidebar, settings( + self.shared.static_root_path.as_deref().unwrap_or("./"), + &self.shared.resource_suffix + ), &themes); self.shared.fs.write(&settings_file, v.as_bytes())?; From a502e856034bcd4bc38152b3bd74cad792b62c63 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sat, 31 Aug 2019 12:31:55 -0400 Subject: [PATCH 15/17] AllTypes to function --- src/librustdoc/html/render.rs | 62 +++++++++++++++++------------------ 1 file changed, 30 insertions(+), 32 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 2eb2ba4e2b201..ee7981aba013a 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1757,8 +1757,7 @@ impl AllTypes { } } -fn print_entries(f: &mut fmt::Formatter<'_>, e: &FxHashSet, title: &str, - class: &str) -> fmt::Result { +fn print_entries(f: &mut Buffer, e: &FxHashSet, title: &str, class: &str) { if !e.is_empty() { let mut e: Vec<&ItemEntry> = e.iter().collect(); e.sort(); @@ -1766,39 +1765,38 @@ fn print_entries(f: &mut fmt::Formatter<'_>, e: &FxHashSet, title: &s title, Escape(title), class, - e.iter().map(|s| format!("
  • {}
  • ", s)).collect::())?; + e.iter().map(|s| format!("
  • {}
  • ", s)).collect::()); } - Ok(()) } -impl fmt::Display for AllTypes { -fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, -"

    \ - \ - \ - \ - []\ - \ +impl AllTypes { + fn print(self, f: &mut Buffer) { + write!(f, + "

    \ + \ + \ + \ + []\ + \ + - - List of all items\ -

    ")?; - print_entries(f, &self.structs, "Structs", "structs")?; - print_entries(f, &self.enums, "Enums", "enums")?; - print_entries(f, &self.unions, "Unions", "unions")?; - print_entries(f, &self.primitives, "Primitives", "primitives")?; - print_entries(f, &self.traits, "Traits", "traits")?; - print_entries(f, &self.macros, "Macros", "macros")?; - print_entries(f, &self.attributes, "Attribute Macros", "attributes")?; - print_entries(f, &self.derives, "Derive Macros", "derives")?; - print_entries(f, &self.functions, "Functions", "functions")?; - print_entries(f, &self.typedefs, "Typedefs", "typedefs")?; - print_entries(f, &self.trait_aliases, "Trait Aliases", "trait-aliases")?; - print_entries(f, &self.opaque_tys, "Opaque Types", "opaque-types")?; - print_entries(f, &self.statics, "Statics", "statics")?; - print_entries(f, &self.constants, "Constants", "constants") -} + List of all items\ +

    "); + print_entries(f, &self.structs, "Structs", "structs"); + print_entries(f, &self.enums, "Enums", "enums"); + print_entries(f, &self.unions, "Unions", "unions"); + print_entries(f, &self.primitives, "Primitives", "primitives"); + print_entries(f, &self.traits, "Traits", "traits"); + print_entries(f, &self.macros, "Macros", "macros"); + print_entries(f, &self.attributes, "Attribute Macros", "attributes"); + print_entries(f, &self.derives, "Derive Macros", "derives"); + print_entries(f, &self.functions, "Functions", "functions"); + print_entries(f, &self.typedefs, "Typedefs", "typedefs"); + print_entries(f, &self.trait_aliases, "Trait Aliases", "trait-aliases"); + print_entries(f, &self.opaque_tys, "Opaque Types", "opaque-types"); + print_entries(f, &self.statics, "Statics", "statics"); + print_entries(f, &self.constants, "Constants", "constants") + } } fn settings(root_path: &str, suffix: &str) -> String { @@ -1901,7 +1899,7 @@ impl Context { String::new() }; let v = layout::render(&self.shared.layout, - &page, sidebar, |buf: &mut Buffer| buf.from_display(all), + &page, sidebar, |buf: &mut Buffer| all.print(buf), &self.shared.themes); self.shared.fs.write(&final_file, v.as_bytes())?; From c1c1e86d5a03796ec4442372b185fb1e20d81124 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sat, 31 Aug 2019 13:29:31 -0400 Subject: [PATCH 16/17] Item to function --- src/librustdoc/html/render.rs | 163 ++++++++++++++++------------------ 1 file changed, 79 insertions(+), 84 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index ee7981aba013a..fc23ffe2b8ca7 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -381,12 +381,6 @@ pub struct RenderInfo { // Helper structs for rendering items/sidebars and carrying along contextual // information -#[derive(Copy, Clone)] -struct Item<'a> { - cx: &'a Context, - item: &'a clean::Item, -} - /// Struct representing one entry in the JS search index. These are all emitted /// by hand to a large JS file at the end of cache-creation. #[derive(Debug)] @@ -1974,7 +1968,7 @@ impl Context { if !self.render_redirect_pages { layout::render(&self.shared.layout, &page, |buf: &mut _| print_sidebar(self, it, buf), - |buf: &mut Buffer| buf.from_display(Item { cx: self, item: it }), + |buf: &mut _| print_item(self, it, buf), &self.shared.themes) } else { let mut url = self.root_path(); @@ -2115,7 +2109,7 @@ impl Context { } } -impl<'a> Item<'a> { +impl Context { /// Generates a url appropriate for an `href` attribute back to the source of /// this item. /// @@ -2125,26 +2119,26 @@ impl<'a> Item<'a> { /// If `None` is returned, then a source link couldn't be generated. This /// may happen, for example, with externally inlined items where the source /// of their crate documentation isn't known. - fn src_href(&self) -> Option { - let mut root = self.cx.root_path(); + fn src_href(&self, item: &clean::Item) -> Option { + let mut root = self.root_path(); let cache = cache(); let mut path = String::new(); // We can safely ignore macros from other libraries - let file = match self.item.source.filename { + let file = match item.source.filename { FileName::Real(ref path) => path, _ => return None, }; - let (krate, path) = if self.item.def_id.is_local() { - if let Some(path) = self.cx.shared.local_sources.get(file) { - (&self.cx.shared.layout.krate, path) + let (krate, path) = if item.def_id.is_local() { + if let Some(path) = self.shared.local_sources.get(file) { + (&self.shared.layout.krate, path) } else { return None; } } else { - let (krate, src_root) = match *cache.extern_locations.get(&self.item.def_id.krate)? { + let (krate, src_root) = match *cache.extern_locations.get(&item.def_id.krate)? { (ref name, ref src, Local) => (name, src), (ref name, ref src, Remote(ref s)) => { root = s.to_string(); @@ -2164,10 +2158,10 @@ impl<'a> Item<'a> { (krate, &path) }; - let lines = if self.item.source.loline == self.item.source.hiline { - self.item.source.loline.to_string() + let lines = if item.source.loline == item.source.hiline { + item.source.loline.to_string() } else { - format!("{}-{}", self.item.source.loline, self.item.source.hiline) + format!("{}-{}", item.source.loline, item.source.hiline) }; Some(format!("{root}src/{krate}/{path}#{lines}", root = Escape(&root), @@ -2185,22 +2179,21 @@ where F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result { write!(w, "") } -impl<'a> fmt::Display for Item<'a> { -fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - debug_assert!(!self.item.is_stripped()); +fn print_item(cx: &Context, item: &clean::Item, buf: &mut Buffer) { + debug_assert!(!item.is_stripped()); // Write the breadcrumb trail header for the top - write!(fmt, "

    ")?; - if let Some(version) = self.item.stable_since() { - write!(fmt, "{0}", - version)?; + write!(buf, "

    "); + if let Some(version) = item.stable_since() { + write!(buf, "{0}", + version); } - write!(fmt, + write!(buf, "\ \ []\ \ - ")?; + "); // Write `src` tag // @@ -2208,85 +2201,87 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { // [src] link in the downstream documentation will actually come back to // this page, and this link will be auto-clicked. The `id` attribute is // used to find the link to auto-click. - if self.cx.shared.include_sources && !self.item.is_primitive() { - if let Some(l) = self.src_href() { - write!(fmt, "[src]", - l, "goto source code")?; + if cx.shared.include_sources && !item.is_primitive() { + if let Some(l) = cx.src_href(item) { + write!(buf, "[src]", + l, "goto source code"); } } - write!(fmt, "")?; // out-of-band - write!(fmt, "")?; - match self.item.inner { + write!(buf, ""); // out-of-band + write!(buf, ""); + let name = match item.inner { clean::ModuleItem(ref m) => if m.is_crate { - write!(fmt, "Crate ")?; + "Crate " } else { - write!(fmt, "Module ")?; + "Module " }, - clean::FunctionItem(..) | clean::ForeignFunctionItem(..) => write!(fmt, "Function ")?, - clean::TraitItem(..) => write!(fmt, "Trait ")?, - clean::StructItem(..) => write!(fmt, "Struct ")?, - clean::UnionItem(..) => write!(fmt, "Union ")?, - clean::EnumItem(..) => write!(fmt, "Enum ")?, - clean::TypedefItem(..) => write!(fmt, "Type Definition ")?, - clean::MacroItem(..) => write!(fmt, "Macro ")?, + clean::FunctionItem(..) | clean::ForeignFunctionItem(..) => "Function ", + clean::TraitItem(..) => "Trait ", + clean::StructItem(..) => "Struct ", + clean::UnionItem(..) => "Union ", + clean::EnumItem(..) => "Enum ", + clean::TypedefItem(..) => "Type Definition ", + clean::MacroItem(..) => "Macro ", clean::ProcMacroItem(ref mac) => match mac.kind { - MacroKind::Bang => write!(fmt, "Macro ")?, - MacroKind::Attr => write!(fmt, "Attribute Macro ")?, - MacroKind::Derive => write!(fmt, "Derive Macro ")?, - } - clean::PrimitiveItem(..) => write!(fmt, "Primitive Type ")?, - clean::StaticItem(..) | clean::ForeignStaticItem(..) => write!(fmt, "Static ")?, - clean::ConstantItem(..) => write!(fmt, "Constant ")?, - clean::ForeignTypeItem => write!(fmt, "Foreign Type ")?, - clean::KeywordItem(..) => write!(fmt, "Keyword ")?, - clean::OpaqueTyItem(..) => write!(fmt, "Opaque Type ")?, - clean::TraitAliasItem(..) => write!(fmt, "Trait Alias ")?, + MacroKind::Bang => "Macro ", + MacroKind::Attr => "Attribute Macro ", + MacroKind::Derive => "Derive Macro ", + } + clean::PrimitiveItem(..) => "Primitive Type ", + clean::StaticItem(..) | clean::ForeignStaticItem(..) => "Static ", + clean::ConstantItem(..) => "Constant ", + clean::ForeignTypeItem => "Foreign Type ", + clean::KeywordItem(..) => "Keyword ", + clean::OpaqueTyItem(..) => "Opaque Type ", + clean::TraitAliasItem(..) => "Trait Alias ", _ => { // We don't generate pages for any other type. unreachable!(); } - } - if !self.item.is_primitive() && !self.item.is_keyword() { - let cur = &self.cx.current; - let amt = if self.item.is_mod() { cur.len() - 1 } else { cur.len() }; + }; + buf.write_str(name); + if !item.is_primitive() && !item.is_keyword() { + let cur = &cx.current; + let amt = if item.is_mod() { cur.len() - 1 } else { cur.len() }; for (i, component) in cur.iter().enumerate().take(amt) { - write!(fmt, "{}::", + write!(buf, "{}::", "../".repeat(cur.len() - i - 1), - component)?; + component); } } - write!(fmt, "{}", - self.item.type_(), self.item.name.as_ref().unwrap())?; + write!(buf, "{}", + item.type_(), item.name.as_ref().unwrap()); - write!(fmt, "

    ")?; // in-band + write!(buf, "

    "); // in-band - match self.item.inner { + buf.with_formatter(|fmt| { + match item.inner { clean::ModuleItem(ref m) => - item_module(fmt, self.cx, self.item, &m.items), + item_module(fmt, cx, item, &m.items), clean::FunctionItem(ref f) | clean::ForeignFunctionItem(ref f) => - item_function(fmt, self.cx, self.item, f), - clean::TraitItem(ref t) => item_trait(fmt, self.cx, self.item, t), - clean::StructItem(ref s) => item_struct(fmt, self.cx, self.item, s), - clean::UnionItem(ref s) => item_union(fmt, self.cx, self.item, s), - clean::EnumItem(ref e) => item_enum(fmt, self.cx, self.item, e), - clean::TypedefItem(ref t, _) => item_typedef(fmt, self.cx, self.item, t), - clean::MacroItem(ref m) => item_macro(fmt, self.cx, self.item, m), - clean::ProcMacroItem(ref m) => item_proc_macro(fmt, self.cx, self.item, m), - clean::PrimitiveItem(ref p) => item_primitive(fmt, self.cx, self.item, p), + item_function(fmt, cx, item, f), + clean::TraitItem(ref t) => item_trait(fmt, cx, item, t), + clean::StructItem(ref s) => item_struct(fmt, cx, item, s), + clean::UnionItem(ref s) => item_union(fmt, cx, item, s), + clean::EnumItem(ref e) => item_enum(fmt, cx, item, e), + clean::TypedefItem(ref t, _) => item_typedef(fmt, cx, item, t), + clean::MacroItem(ref m) => item_macro(fmt, cx, item, m), + clean::ProcMacroItem(ref m) => item_proc_macro(fmt, cx, item, m), + clean::PrimitiveItem(ref p) => item_primitive(fmt, cx, item, p), clean::StaticItem(ref i) | clean::ForeignStaticItem(ref i) => - item_static(fmt, self.cx, self.item, i), - clean::ConstantItem(ref c) => item_constant(fmt, self.cx, self.item, c), - clean::ForeignTypeItem => item_foreign_type(fmt, self.cx, self.item), - clean::KeywordItem(ref k) => item_keyword(fmt, self.cx, self.item, k), - clean::OpaqueTyItem(ref e, _) => item_opaque_ty(fmt, self.cx, self.item, e), - clean::TraitAliasItem(ref ta) => item_trait_alias(fmt, self.cx, self.item, ta), + item_static(fmt, cx, item, i), + clean::ConstantItem(ref c) => item_constant(fmt, cx, item, c), + clean::ForeignTypeItem => item_foreign_type(fmt, cx, item), + clean::KeywordItem(ref k) => item_keyword(fmt, cx, item, k), + clean::OpaqueTyItem(ref e, _) => item_opaque_ty(fmt, cx, item, e), + clean::TraitAliasItem(ref ta) => item_trait_alias(fmt, cx, item, ta), _ => { // We don't generate pages for any other type. unreachable!(); } } -} + }) } fn item_path(ty: ItemType, name: &str) -> String { @@ -4004,7 +3999,7 @@ fn render_impl(w: &mut fmt::Formatter<'_>, cx: &Context, i: &Impl, link: AssocIt write!(w, "", id)?; let since = i.impl_item.stability.as_ref().map(|s| &s.since[..]); render_stability_since_raw(w, since, outer_version)?; - if let Some(l) = (Item { item: &i.impl_item, cx: cx }).src_href() { + if let Some(l) = cx.src_href(&i.impl_item) { write!(w, "[src]", l, "goto source code")?; } @@ -4050,7 +4045,7 @@ fn render_impl(w: &mut fmt::Formatter<'_>, cx: &Context, i: &Impl, link: AssocIt render_assoc_item(w, item, link.anchor(&id), ItemType::Impl)?; write!(w, "")?; render_stability_since_raw(w, item.stable_since(), outer_version)?; - if let Some(l) = (Item { cx, item }).src_href() { + if let Some(l) = cx.src_href(item) { write!(w, "[src]", l, "goto source code")?; } @@ -4073,7 +4068,7 @@ fn render_impl(w: &mut fmt::Formatter<'_>, cx: &Context, i: &Impl, link: AssocIt assoc_const(w, item, ty, default.as_ref(), link.anchor(&id), "")?; write!(w, "")?; render_stability_since_raw(w, item.stable_since(), outer_version)?; - if let Some(l) = (Item { cx, item }).src_href() { + if let Some(l) = cx.src_href(item) { write!(w, "[src]", l, "goto source code")?; } From 02c5c5cb597c873dd152f3ec8a6b74b5f28ccf36 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sat, 31 Aug 2019 15:47:55 -0400 Subject: [PATCH 17/17] Move to buffers throughout print_item --- src/librustdoc/html/format.rs | 6 +- src/librustdoc/html/render.rs | 797 ++++++++++++++++------------------ 2 files changed, 375 insertions(+), 428 deletions(-) diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 80f34fb17d2e8..dcd32192ff384 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -872,9 +872,9 @@ impl fmt::Display for clean::Impl { // The difference from above is that trait is not hyperlinked. pub fn fmt_impl_for_trait_page(i: &clean::Impl, - f: &mut fmt::Formatter<'_>, - use_absolute: bool) -> fmt::Result { - fmt_impl(i, f, false, use_absolute) + f: &mut Buffer, + use_absolute: bool) { + f.with_formatter(|f| fmt_impl(i, f, false, use_absolute)) } impl fmt::Display for clean::Arguments { diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index fc23ffe2b8ca7..9846073cad4bc 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1233,9 +1233,9 @@ themePicker.onblur = handleThemeButtonsBlur; // identically even with rustdoc running in parallel. all_implementors.sort(); - let mut v = String::from("(function() {var implementors = {}};\n"); + let mut v = String::from("(function() {var implementors = {};\n"); for implementor in &all_implementors { - v.push_str(&format!("{}", *implementor)); + writeln!(v, "{}", *implementor).unwrap(); } v.push_str(r" if (window.register_implementors) { @@ -1243,7 +1243,7 @@ themePicker.onblur = handleThemeButtonsBlur; } else { window.pending_implementors = implementors; } - \n"); + "); v.push_str("})()"); cx.shared.fs.write(&mydst, &v)?; } @@ -2171,11 +2171,11 @@ impl Context { } } -fn wrap_into_docblock(w: &mut fmt::Formatter<'_>, - f: F) -> fmt::Result -where F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result { - write!(w, "
    ")?; - f(w)?; +fn wrap_into_docblock(w: &mut Buffer, f: F) + where F: FnOnce(&mut Buffer) +{ + write!(w, "
    "); + f(w); write!(w, "
    ") } @@ -2255,33 +2255,31 @@ fn print_item(cx: &Context, item: &clean::Item, buf: &mut Buffer) { write!(buf, ""); // in-band - buf.with_formatter(|fmt| { match item.inner { clean::ModuleItem(ref m) => - item_module(fmt, cx, item, &m.items), + item_module(buf, cx, item, &m.items), clean::FunctionItem(ref f) | clean::ForeignFunctionItem(ref f) => - item_function(fmt, cx, item, f), - clean::TraitItem(ref t) => item_trait(fmt, cx, item, t), - clean::StructItem(ref s) => item_struct(fmt, cx, item, s), - clean::UnionItem(ref s) => item_union(fmt, cx, item, s), - clean::EnumItem(ref e) => item_enum(fmt, cx, item, e), - clean::TypedefItem(ref t, _) => item_typedef(fmt, cx, item, t), - clean::MacroItem(ref m) => item_macro(fmt, cx, item, m), - clean::ProcMacroItem(ref m) => item_proc_macro(fmt, cx, item, m), - clean::PrimitiveItem(ref p) => item_primitive(fmt, cx, item, p), + item_function(buf, cx, item, f), + clean::TraitItem(ref t) => item_trait(buf, cx, item, t), + clean::StructItem(ref s) => item_struct(buf, cx, item, s), + clean::UnionItem(ref s) => item_union(buf, cx, item, s), + clean::EnumItem(ref e) => item_enum(buf, cx, item, e), + clean::TypedefItem(ref t, _) => item_typedef(buf, cx, item, t), + clean::MacroItem(ref m) => item_macro(buf, cx, item, m), + clean::ProcMacroItem(ref m) => item_proc_macro(buf, cx, item, m), + clean::PrimitiveItem(ref p) => item_primitive(buf, cx, item, p), clean::StaticItem(ref i) | clean::ForeignStaticItem(ref i) => - item_static(fmt, cx, item, i), - clean::ConstantItem(ref c) => item_constant(fmt, cx, item, c), - clean::ForeignTypeItem => item_foreign_type(fmt, cx, item), - clean::KeywordItem(ref k) => item_keyword(fmt, cx, item, k), - clean::OpaqueTyItem(ref e, _) => item_opaque_ty(fmt, cx, item, e), - clean::TraitAliasItem(ref ta) => item_trait_alias(fmt, cx, item, ta), + item_static(buf, cx, item, i), + clean::ConstantItem(ref c) => item_constant(buf, cx, item, c), + clean::ForeignTypeItem => item_foreign_type(buf, cx, item), + clean::KeywordItem(ref k) => item_keyword(buf, cx, item, k), + clean::OpaqueTyItem(ref e, _) => item_opaque_ty(buf, cx, item, e), + clean::TraitAliasItem(ref ta) => item_trait_alias(buf, cx, item, ta), _ => { // We don't generate pages for any other type. unreachable!(); } } - }) } fn item_path(ty: ItemType, name: &str) -> String { @@ -2333,24 +2331,23 @@ fn shorten(s: String) -> String { } } -fn document(w: &mut fmt::Formatter<'_>, cx: &Context, item: &clean::Item) -> fmt::Result { +fn document(w: &mut Buffer, cx: &Context, item: &clean::Item) { if let Some(ref name) = item.name { info!("Documenting {}", name); } - document_stability(w, cx, item, false)?; - document_full(w, item, cx, "", false)?; - Ok(()) + document_stability(w, cx, item, false); + document_full(w, item, cx, "", false); } /// Render md_text as markdown. fn render_markdown( - w: &mut fmt::Formatter<'_>, + w: &mut Buffer, cx: &Context, md_text: &str, links: Vec<(String, String)>, prefix: &str, is_hidden: bool, -) -> fmt::Result { +) { let mut ids = cx.id_map.borrow_mut(); write!(w, "
    {}{}
    ", if is_hidden { " hidden" } else { "" }, @@ -2360,13 +2357,13 @@ fn render_markdown( } fn document_short( - w: &mut fmt::Formatter<'_>, + w: &mut Buffer, cx: &Context, item: &clean::Item, link: AssocItemLink<'_>, prefix: &str, is_hidden: bool, -) -> fmt::Result { +) { if let Some(s) = item.doc_value() { let markdown = if s.contains('\n') { format!("{} [Read more]({})", @@ -2374,46 +2371,41 @@ fn document_short( } else { plain_summary_line(Some(s)) }; - render_markdown(w, cx, &markdown, item.links(), prefix, is_hidden)?; + render_markdown(w, cx, &markdown, item.links(), prefix, is_hidden); } else if !prefix.is_empty() { write!(w, "
    {}
    ", if is_hidden { " hidden" } else { "" }, - prefix)?; + prefix); } - Ok(()) } -fn document_full(w: &mut fmt::Formatter<'_>, item: &clean::Item, - cx: &Context, prefix: &str, is_hidden: bool) -> fmt::Result { +fn document_full(w: &mut Buffer, item: &clean::Item, cx: &Context, prefix: &str, is_hidden: bool) { if let Some(s) = cx.shared.maybe_collapsed_doc_value(item) { debug!("Doc block: =====\n{}\n=====", s); - render_markdown(w, cx, &*s, item.links(), prefix, is_hidden)?; + render_markdown(w, cx, &*s, item.links(), prefix, is_hidden); } else if !prefix.is_empty() { write!(w, "
    {}
    ", if is_hidden { " hidden" } else { "" }, - prefix)?; + prefix); } - Ok(()) } -fn document_stability(w: &mut fmt::Formatter<'_>, cx: &Context, item: &clean::Item, - is_hidden: bool) -> fmt::Result { +fn document_stability(w: &mut Buffer, cx: &Context, item: &clean::Item, is_hidden: bool) { let stabilities = short_stability(item, cx); if !stabilities.is_empty() { - write!(w, "
    ", if is_hidden { " hidden" } else { "" })?; + write!(w, "
    ", if is_hidden { " hidden" } else { "" }); for stability in stabilities { - write!(w, "{}", stability)?; + write!(w, "{}", stability); } - write!(w, "
    ")?; + write!(w, "
    "); } - Ok(()) } fn document_non_exhaustive_header(item: &clean::Item) -> &str { if item.is_non_exhaustive() { " (Non-exhaustive)" } else { "" } } -fn document_non_exhaustive(w: &mut fmt::Formatter<'_>, item: &clean::Item) -> fmt::Result { +fn document_non_exhaustive(w: &mut Buffer, item: &clean::Item) { if item.is_non_exhaustive() { write!(w, "
    ", { if item.is_struct() { @@ -2425,31 +2417,29 @@ fn document_non_exhaustive(w: &mut fmt::Formatter<'_>, item: &clean::Item) -> fm } else { "type" } - })?; + }); if item.is_struct() { write!(w, "Non-exhaustive structs could have additional fields added in future. \ Therefore, non-exhaustive structs cannot be constructed in external crates \ using the traditional Struct {{ .. }} syntax; cannot be \ matched against without a wildcard ..; and \ - struct update syntax will not work.")?; + struct update syntax will not work."); } else if item.is_enum() { write!(w, "Non-exhaustive enums could have additional variants added in future. \ Therefore, when matching against variants of non-exhaustive enums, an \ - extra wildcard arm must be added to account for any future variants.")?; + extra wildcard arm must be added to account for any future variants."); } else if item.is_variant() { write!(w, "Non-exhaustive enum variants could have additional fields added in future. \ Therefore, non-exhaustive enum variants cannot be constructed in external \ - crates and cannot be matched against.")?; + crates and cannot be matched against."); } else { write!(w, "This type will require a wildcard arm in any match statements or \ - constructors.")?; + constructors."); } - write!(w, "
    ")?; + write!(w, "
    "); } - - Ok(()) } fn name_key(name: &str) -> (&str, u64, usize) { @@ -2473,9 +2463,8 @@ fn name_key(name: &str) -> (&str, u64, usize) { } } -fn item_module(w: &mut fmt::Formatter<'_>, cx: &Context, - item: &clean::Item, items: &[clean::Item]) -> fmt::Result { - document(w, cx, item)?; +fn item_module(w: &mut Buffer, cx: &Context, item: &clean::Item, items: &[clean::Item]) { + document(w, cx, item); let mut indices = (0..items.len()).filter(|i| !items[*i].is_stripped()).collect::>(); @@ -2566,13 +2555,13 @@ fn item_module(w: &mut fmt::Formatter<'_>, cx: &Context, curty = myty; } else if myty != curty { if curty.is_some() { - write!(w, "")?; + write!(w, ""); } curty = myty; let (short, name) = item_ty_to_strs(&myty.unwrap()); write!(w, "

    \ {name}

    \n", - id = cx.derive_id(short.to_owned()), name = name)?; + id = cx.derive_id(short.to_owned()), name = name); } match myitem.inner { @@ -2584,20 +2573,20 @@ fn item_module(w: &mut fmt::Formatter<'_>, cx: &Context, write!(w, "")?; + write!(w, ""); } clean::ImportItem(ref import) => { write!(w, "", - VisSpace(&myitem.visibility), *import)?; + VisSpace(&myitem.visibility), *import); } _ => { @@ -2642,15 +2631,14 @@ fn item_module(w: &mut fmt::Formatter<'_>, cx: &Context, }) .collect::>() .join(" "), - )?; + ); } } } if curty.is_some() { - write!(w, "
    {}extern crate {} as {};", VisSpace(&myitem.visibility), anchor(myitem.def_id, src), - name)? + name) } None => { write!(w, "
    {}extern crate {};", VisSpace(&myitem.visibility), - anchor(myitem.def_id, name))? + anchor(myitem.def_id, name)) } } - write!(w, "
    {}{}
    ")?; + write!(w, ""); } - Ok(()) } /// Render the stability and deprecation tags that are displayed in the item's summary at the @@ -2799,33 +2787,30 @@ fn short_stability(item: &clean::Item, cx: &Context) -> Vec { stability } -fn item_constant(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item, - c: &clean::Constant) -> fmt::Result { - write!(w, "
    ")?;
    -    render_attributes(w, it, false)?;
    +fn item_constant(w: &mut Buffer, cx: &Context, it: &clean::Item, c: &clean::Constant) {
    +    write!(w, "
    ");
    +    render_attributes(w, it, false);
         write!(w, "{vis}const \
                    {name}: {typ}
    ", vis = VisSpace(&it.visibility), name = it.name.as_ref().unwrap(), - typ = c.type_)?; + typ = c.type_); document(w, cx, it) } -fn item_static(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item, - s: &clean::Static) -> fmt::Result { - write!(w, "
    ")?;
    -    render_attributes(w, it, false)?;
    +fn item_static(w: &mut Buffer, cx: &Context, it: &clean::Item, s: &clean::Static) {
    +    write!(w, "
    ");
    +    render_attributes(w, it, false);
         write!(w, "{vis}static {mutability}\
                    {name}: {typ}
    ", vis = VisSpace(&it.visibility), mutability = MutableSpace(s.mutability), name = it.name.as_ref().unwrap(), - typ = s.type_)?; + typ = s.type_); document(w, cx, it) } -fn item_function(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item, - f: &clean::Function) -> fmt::Result { +fn item_function(w: &mut Buffer, cx: &Context, it: &clean::Item, f: &clean::Function) { let header_len = format!( "{}{}{}{}{:#}fn {}{:#}", VisSpace(&it.visibility), @@ -2836,8 +2821,8 @@ fn item_function(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item, it.name.as_ref().unwrap(), f.generics ).len(); - write!(w, "{}
    ", render_spotlight_traits(it)?)?;
    -    render_attributes(w, it, false)?;
    +    write!(w, "{}
    ", render_spotlight_traits(it));
    +    render_attributes(w, it, false);
         write!(w,
                "{vis}{constness}{unsafety}{asyncness}{abi}fn \
                {name}{generics}{decl}{where_clause}
    ", @@ -2854,12 +2839,12 @@ fn item_function(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item, header_len, indent: 0, asyncness: f.header.asyncness, - })?; + }); document(w, cx, it) } -fn render_implementor(cx: &Context, implementor: &Impl, w: &mut fmt::Formatter<'_>, - implementor_dups: &FxHashMap<&str, (DefId, bool)>) -> fmt::Result { +fn render_implementor(cx: &Context, implementor: &Impl, w: &mut Buffer, + implementor_dups: &FxHashMap<&str, (DefId, bool)>) { // If there's already another implementor that has the same abbridged name, use the // full path, for example in `std::iter::ExactSizeIterator` let use_absolute = match implementor.inner_impl().for_ { @@ -2871,20 +2856,18 @@ fn render_implementor(cx: &Context, implementor: &Impl, w: &mut fmt::Formatter<' _ => false, }; render_impl(w, cx, implementor, AssocItemLink::Anchor(None), RenderMode::Normal, - implementor.impl_item.stable_since(), false, Some(use_absolute), false, false)?; - Ok(()) + implementor.impl_item.stable_since(), false, Some(use_absolute), false, false); } -fn render_impls(cx: &Context, w: &mut fmt::Formatter<'_>, +fn render_impls(cx: &Context, w: &mut Buffer, traits: &[&&Impl], - containing_item: &clean::Item) -> fmt::Result { + containing_item: &clean::Item) { for i in traits { let did = i.trait_did().unwrap(); let assoc_link = AssocItemLink::GotoSource(did, &i.inner_impl().provided_trait_methods); render_impl(w, cx, i, assoc_link, - RenderMode::Normal, containing_item.stable_since(), true, None, false, true)?; + RenderMode::Normal, containing_item.stable_since(), true, None, false, true); } - Ok(()) } fn bounds(t_bounds: &[clean::GenericBound], trait_alias: bool) -> String { @@ -2912,11 +2895,11 @@ fn compare_impl<'a, 'b>(lhs: &'a &&Impl, rhs: &'b &&Impl) -> Ordering { } fn item_trait( - w: &mut fmt::Formatter<'_>, + w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Trait, -) -> fmt::Result { +) { let bounds = bounds(&t.bounds, false); let types = t.items.iter().filter(|m| m.is_associated_type()).collect::>(); let consts = t.items.iter().filter(|m| m.is_associated_const()).collect::>(); @@ -2925,146 +2908,144 @@ fn item_trait( // Output the trait definition wrap_into_docblock(w, |w| { - write!(w, "
    ")?;
    -        render_attributes(w, it, true)?;
    +        write!(w, "
    ");
    +        render_attributes(w, it, true);
             write!(w, "{}{}{}trait {}{}{}",
                    VisSpace(&it.visibility),
                    UnsafetySpace(t.unsafety),
                    if t.is_auto { "auto " } else { "" },
                    it.name.as_ref().unwrap(),
                    t.generics,
    -               bounds)?;
    +               bounds);
     
             if !t.generics.where_predicates.is_empty() {
    -            write!(w, "{}", WhereClause { gens: &t.generics, indent: 0, end_newline: true })?;
    +            write!(w, "{}", WhereClause { gens: &t.generics, indent: 0, end_newline: true });
             } else {
    -            write!(w, " ")?;
    +            write!(w, " ");
             }
     
             if t.items.is_empty() {
    -            write!(w, "{{ }}")?;
    +            write!(w, "{{ }}");
             } else {
                 // FIXME: we should be using a derived_id for the Anchors here
    -            write!(w, "{{\n")?;
    +            write!(w, "{{\n");
                 for t in &types {
    -                render_assoc_item(w, t, AssocItemLink::Anchor(None), ItemType::Trait)?;
    -                write!(w, ";\n")?;
    +                render_assoc_item(w, t, AssocItemLink::Anchor(None), ItemType::Trait);
    +                write!(w, ";\n");
                 }
                 if !types.is_empty() && !consts.is_empty() {
    -                w.write_str("\n")?;
    +                w.write_str("\n");
                 }
                 for t in &consts {
    -                render_assoc_item(w, t, AssocItemLink::Anchor(None), ItemType::Trait)?;
    -                write!(w, ";\n")?;
    +                render_assoc_item(w, t, AssocItemLink::Anchor(None), ItemType::Trait);
    +                write!(w, ";\n");
                 }
                 if !consts.is_empty() && !required.is_empty() {
    -                w.write_str("\n")?;
    +                w.write_str("\n");
                 }
                 for (pos, m) in required.iter().enumerate() {
    -                render_assoc_item(w, m, AssocItemLink::Anchor(None), ItemType::Trait)?;
    -                write!(w, ";\n")?;
    +                render_assoc_item(w, m, AssocItemLink::Anchor(None), ItemType::Trait);
    +                write!(w, ";\n");
     
                     if pos < required.len() - 1 {
    -                   write!(w, "
    ")?; + write!(w, "
    "); } } if !required.is_empty() && !provided.is_empty() { - w.write_str("\n")?; + w.write_str("\n"); } for (pos, m) in provided.iter().enumerate() { - render_assoc_item(w, m, AssocItemLink::Anchor(None), ItemType::Trait)?; + render_assoc_item(w, m, AssocItemLink::Anchor(None), ItemType::Trait); match m.inner { clean::MethodItem(ref inner) if !inner.generics.where_predicates.is_empty() => { - write!(w, ",\n {{ ... }}\n")?; + write!(w, ",\n {{ ... }}\n"); }, _ => { - write!(w, " {{ ... }}\n")?; + write!(w, " {{ ... }}\n"); }, } if pos < provided.len() - 1 { - write!(w, "
    ")?; + write!(w, "
    "); } } - write!(w, "}}")?; + write!(w, "}}"); } write!(w, "
    ") - })?; + }); // Trait documentation - document(w, cx, it)?; + document(w, cx, it); fn write_small_section_header( - w: &mut fmt::Formatter<'_>, + w: &mut Buffer, id: &str, title: &str, extra_content: &str, - ) -> fmt::Result { + ) { write!(w, "

    \ {1}\

    {2}", id, title, extra_content) } - fn write_loading_content(w: &mut fmt::Formatter<'_>, extra_content: &str) -> fmt::Result { + fn write_loading_content(w: &mut Buffer, extra_content: &str) { write!(w, "{}Loading content...", extra_content) } - fn trait_item(w: &mut fmt::Formatter<'_>, cx: &Context, m: &clean::Item, t: &clean::Item) - -> fmt::Result { + fn trait_item(w: &mut Buffer, cx: &Context, m: &clean::Item, t: &clean::Item) { let name = m.name.as_ref().unwrap(); let item_type = m.type_(); let id = cx.derive_id(format!("{}.{}", item_type, name)); let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space())); write!(w, "

    {extra}", - extra = render_spotlight_traits(m)?, + extra = render_spotlight_traits(m), id = id, - ns_id = ns_id)?; - render_assoc_item(w, m, AssocItemLink::Anchor(Some(&id)), ItemType::Impl)?; - write!(w, "")?; - render_stability_since(w, m, t)?; - write!(w, "

    ")?; - document(w, cx, m)?; - Ok(()) + ns_id = ns_id); + render_assoc_item(w, m, AssocItemLink::Anchor(Some(&id)), ItemType::Impl); + write!(w, ""); + render_stability_since(w, m, t); + write!(w, ""); + document(w, cx, m); } if !types.is_empty() { write_small_section_header(w, "associated-types", "Associated Types", - "
    ")?; + "
    "); for t in &types { - trait_item(w, cx, *t, it)?; + trait_item(w, cx, *t, it); } - write_loading_content(w, "
    ")?; + write_loading_content(w, "
    "); } if !consts.is_empty() { write_small_section_header(w, "associated-const", "Associated Constants", - "
    ")?; + "
    "); for t in &consts { - trait_item(w, cx, *t, it)?; + trait_item(w, cx, *t, it); } - write_loading_content(w, "
    ")?; + write_loading_content(w, "
    "); } // Output the documentation for each function individually if !required.is_empty() { write_small_section_header(w, "required-methods", "Required methods", - "
    ")?; + "
    "); for m in &required { - trait_item(w, cx, *m, it)?; + trait_item(w, cx, *m, it); } - write_loading_content(w, "
    ")?; + write_loading_content(w, "
    "); } if !provided.is_empty() { write_small_section_header(w, "provided-methods", "Provided methods", - "
    ")?; + "
    "); for m in &provided { - trait_item(w, cx, *m, it)?; + trait_item(w, cx, *m, it); } - write_loading_content(w, "
    ")?; + write_loading_content(w, "
    "); } // If there are methods directly on this trait object, render them here. - render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All)?; + render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All); let cache = cache(); @@ -3103,7 +3084,7 @@ fn item_trait( concrete.sort_by(compare_impl); if !foreign.is_empty() { - write_small_section_header(w, "foreign-impls", "Implementations on Foreign Types", "")?; + write_small_section_header(w, "foreign-impls", "Implementations on Foreign Types", ""); for implementor in foreign { let assoc_link = AssocItemLink::GotoSource( @@ -3112,44 +3093,44 @@ fn item_trait( ); render_impl(w, cx, &implementor, assoc_link, RenderMode::Normal, implementor.impl_item.stable_since(), false, - None, true, false)?; + None, true, false); } - write_loading_content(w, "")?; + write_loading_content(w, ""); } write_small_section_header(w, "implementors", "Implementors", - "
    ")?; + "
    "); for implementor in concrete { - render_implementor(cx, implementor, w, &implementor_dups)?; + render_implementor(cx, implementor, w, &implementor_dups); } - write_loading_content(w, "
    ")?; + write_loading_content(w, "
    "); if t.auto { write_small_section_header(w, "synthetic-implementors", "Auto implementors", - "
    ")?; + "
    "); for implementor in synthetic { synthetic_types.extend( collect_paths_for_type(implementor.inner_impl().for_.clone()) ); - render_implementor(cx, implementor, w, &implementor_dups)?; + render_implementor(cx, implementor, w, &implementor_dups); } - write_loading_content(w, "
    ")?; + write_loading_content(w, "
    "); } } else { // even without any implementations to write in, we still want the heading and list, so the // implementors javascript file pulled in below has somewhere to write the impls into write_small_section_header(w, "implementors", "Implementors", - "
    ")?; - write_loading_content(w, "
    ")?; + "
    "); + write_loading_content(w, "
    "); if t.auto { write_small_section_header(w, "synthetic-implementors", "Auto implementors", - "
    ")?; - write_loading_content(w, "
    ")?; + "
    "); + write_loading_content(w, "
    "); } } write!(w, r#""#, - as_json(&synthetic_types))?; + as_json(&synthetic_types)); write!(w, r#"