diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index 62def4a94e8..22a6fcd316a 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -17,8 +17,8 @@ use super::search_index::build_index; use super::write_shared::write_shared; use super::{ - collect_spans_and_sources, print_sidebar, scrape_examples_help, AllTypes, LinkFromSrc, NameDoc, - StylePath, BASIC_KEYWORDS, + collect_spans_and_sources, print_sidebar, scrape_examples_help, sidebar_module_like, AllTypes, + LinkFromSrc, NameDoc, StylePath, BASIC_KEYWORDS, }; use crate::clean::{self, types::ExternalLocation, ExternalCrate}; @@ -597,16 +597,24 @@ fn after_krate(&mut self) -> Result<(), Error> { keywords: BASIC_KEYWORDS, resource_suffix: &shared.resource_suffix, }; - let sidebar = if shared.cache.crate_version.is_some() { - format!("

Crate {}

", crate_name) - } else { - String::new() - }; let all = shared.all.replace(AllTypes::new()); + let mut sidebar = Buffer::html(); + if shared.cache.crate_version.is_some() { + write!(sidebar, "

Crate {}

", crate_name) + }; + + let mut items = Buffer::html(); + sidebar_module_like(&mut items, all.item_sections()); + if !items.is_empty() { + sidebar.push_str("
"); + sidebar.push_buffer(items); + sidebar.push_str("
"); + } + let v = layout::render( &shared.layout, &page, - sidebar, + sidebar.into_inner(), |buf: &mut Buffer| all.print(buf), &shared.style_files, ); diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index ced0ebdbb86..7e5e4df43d2 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -290,19 +290,66 @@ fn append(&mut self, item_name: String, item_type: &ItemType) { }; } } -} -impl AllTypes { + fn item_sections(&self) -> FxHashSet { + let mut sections = FxHashSet::default(); + + if !self.structs.is_empty() { + sections.insert(ItemSection::Structs); + } + if !self.enums.is_empty() { + sections.insert(ItemSection::Enums); + } + if !self.unions.is_empty() { + sections.insert(ItemSection::Unions); + } + if !self.primitives.is_empty() { + sections.insert(ItemSection::PrimitiveTypes); + } + if !self.traits.is_empty() { + sections.insert(ItemSection::Traits); + } + if !self.macros.is_empty() { + sections.insert(ItemSection::Macros); + } + if !self.functions.is_empty() { + sections.insert(ItemSection::Functions); + } + if !self.typedefs.is_empty() { + sections.insert(ItemSection::TypeDefinitions); + } + if !self.opaque_tys.is_empty() { + sections.insert(ItemSection::OpaqueTypes); + } + if !self.statics.is_empty() { + sections.insert(ItemSection::Statics); + } + if !self.constants.is_empty() { + sections.insert(ItemSection::Constants); + } + if !self.attributes.is_empty() { + sections.insert(ItemSection::AttributeMacros); + } + if !self.derives.is_empty() { + sections.insert(ItemSection::DeriveMacros); + } + if !self.trait_aliases.is_empty() { + sections.insert(ItemSection::TraitAliases); + } + + sections + } + fn print(self, f: &mut Buffer) { - fn print_entries(f: &mut Buffer, e: &FxHashSet, title: &str) { + fn print_entries(f: &mut Buffer, e: &FxHashSet, kind: ItemSection) { if !e.is_empty() { let mut e: Vec<&ItemEntry> = e.iter().collect(); e.sort(); write!( f, - "

{}

    ", - title.replace(' ', "-"), // IDs cannot contain whitespaces. - title + "

    {title}

      ", + id = kind.id(), + title = kind.name(), ); for s in e.iter() { @@ -320,20 +367,20 @@ fn print_entries(f: &mut Buffer, e: &FxHashSet, title: &str) { ); // Note: print_entries does not escape the title, because we know the current set of titles // doesn't require escaping. - print_entries(f, &self.structs, "Structs"); - print_entries(f, &self.enums, "Enums"); - print_entries(f, &self.unions, "Unions"); - print_entries(f, &self.primitives, "Primitives"); - print_entries(f, &self.traits, "Traits"); - print_entries(f, &self.macros, "Macros"); - print_entries(f, &self.attributes, "Attribute Macros"); - print_entries(f, &self.derives, "Derive Macros"); - print_entries(f, &self.functions, "Functions"); - print_entries(f, &self.typedefs, "Typedefs"); - print_entries(f, &self.trait_aliases, "Trait Aliases"); - print_entries(f, &self.opaque_tys, "Opaque Types"); - print_entries(f, &self.statics, "Statics"); - print_entries(f, &self.constants, "Constants"); + print_entries(f, &self.structs, ItemSection::Structs); + print_entries(f, &self.enums, ItemSection::Enums); + print_entries(f, &self.unions, ItemSection::Unions); + print_entries(f, &self.primitives, ItemSection::PrimitiveTypes); + print_entries(f, &self.traits, ItemSection::Traits); + print_entries(f, &self.macros, ItemSection::Macros); + print_entries(f, &self.attributes, ItemSection::AttributeMacros); + print_entries(f, &self.derives, ItemSection::DeriveMacros); + print_entries(f, &self.functions, ItemSection::Functions); + print_entries(f, &self.typedefs, ItemSection::TypeDefinitions); + print_entries(f, &self.trait_aliases, ItemSection::TraitAliases); + print_entries(f, &self.opaque_tys, ItemSection::OpaqueTypes); + print_entries(f, &self.statics, ItemSection::Statics); + print_entries(f, &self.constants, ItemSection::Constants); } } @@ -2468,7 +2515,7 @@ fn sidebar_enum(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, e: &clean: } #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -enum ItemSection { +pub(crate) enum ItemSection { Reexports, PrimitiveTypes, Modules, @@ -2620,25 +2667,11 @@ fn item_ty_to_section(ty: ItemType) -> ItemSection { } } -fn sidebar_module(buf: &mut Buffer, items: &[clean::Item]) { +pub(crate) fn sidebar_module_like(buf: &mut Buffer, item_sections_in_use: FxHashSet) { use std::fmt::Write as _; let mut sidebar = String::new(); - let item_sections_in_use: FxHashSet<_> = items - .iter() - .filter(|it| { - !it.is_stripped() - && it - .name - .or_else(|| { - if let clean::ImportItem(ref i) = *it.kind && - let clean::ImportKind::Simple(s) = i.kind { Some(s) } else { None } - }) - .is_some() - }) - .map(|it| item_ty_to_section(it.type_())) - .collect(); for &sec in ItemSection::ALL.iter().filter(|sec| item_sections_in_use.contains(sec)) { let _ = write!(sidebar, "
    • {}
    • ", sec.id(), sec.name()); } @@ -2656,6 +2689,25 @@ fn sidebar_module(buf: &mut Buffer, items: &[clean::Item]) { } } +fn sidebar_module(buf: &mut Buffer, items: &[clean::Item]) { + let item_sections_in_use: FxHashSet<_> = items + .iter() + .filter(|it| { + !it.is_stripped() + && it + .name + .or_else(|| { + if let clean::ImportItem(ref i) = *it.kind && + let clean::ImportKind::Simple(s) = i.kind { Some(s) } else { None } + }) + .is_some() + }) + .map(|it| item_ty_to_section(it.type_())) + .collect(); + + sidebar_module_like(buf, item_sections_in_use); +} + fn sidebar_foreign_type(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item) { let mut sidebar = Buffer::new(); sidebar_assoc_items(cx, &mut sidebar, it); diff --git a/src/test/rustdoc/sidebar-all-page.rs b/src/test/rustdoc/sidebar-all-page.rs new file mode 100644 index 00000000000..e74b981de64 --- /dev/null +++ b/src/test/rustdoc/sidebar-all-page.rs @@ -0,0 +1,35 @@ +#![crate_name = "foo"] + +#![feature(rustdoc_internals)] + +// @has 'foo/all.html' +// @has - '//*[@class="sidebar-elems"]//li' 'Structs' +// @has - '//*[@class="sidebar-elems"]//li' 'Enums' +// @has - '//*[@class="sidebar-elems"]//li' 'Unions' +// @has - '//*[@class="sidebar-elems"]//li' 'Functions' +// @has - '//*[@class="sidebar-elems"]//li' 'Traits' +// @has - '//*[@class="sidebar-elems"]//li' 'Macros' +// @has - '//*[@class="sidebar-elems"]//li' 'Type Definitions' +// @has - '//*[@class="sidebar-elems"]//li' 'Constants' +// @has - '//*[@class="sidebar-elems"]//li' 'Statics' +// @has - '//*[@class="sidebar-elems"]//li' 'Primitive Types' + +pub struct Foo; +pub enum Enum { + A, +} +pub union Bar { + a: u8, + b: u16, +} +pub fn foo() {} +pub trait Trait {} +#[macro_export] +macro_rules! foo { + () => {} +} +pub type Type = u8; +pub const FOO: u8 = 0; +pub static BAR: u8 = 0; +#[doc(primitive = "u8")] +mod u8 {}