From fa400ace11f9db1e299fef3992d3301ccd985bf0 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Fri, 7 Jan 2022 16:12:11 -0800 Subject: [PATCH 1/4] rustdoc: Create enum for sections holding items --- src/librustdoc/html/render/mod.rs | 151 ++++++++++++++++++----- src/librustdoc/html/render/print_item.rs | 14 +-- 2 files changed, 128 insertions(+), 37 deletions(-) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 32e4a82918421..3fd94fb9dc522 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -2409,33 +2409,124 @@ fn sidebar_enum(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, e: &clean: } } -fn item_ty_to_strs(ty: ItemType) -> (&'static str, &'static str) { +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +enum ItemSection { + Reexports, + Modules, + Structs, + Unions, + Enums, + Functions, + TypeDefinitions, + Statics, + Constants, + Traits, + Implementations, + TypeMethods, + Methods, + StructFields, + Variants, + Macros, + PrimitiveTypes, + AssociatedTypes, + AssociatedConstants, + ForeignTypes, + Keywords, + OpaqueTypes, + AttributeMacros, + DeriveMacros, + TraitAliases, +} + +impl ItemSection { + fn id(self) -> &'static str { + match self { + Self::Reexports => "reexports", + Self::Modules => "modules", + Self::Structs => "structs", + Self::Unions => "unions", + Self::Enums => "enums", + Self::Functions => "functions", + Self::TypeDefinitions => "types", + Self::Statics => "statics", + Self::Constants => "constants", + Self::Traits => "traits", + Self::Implementations => "impls", + Self::TypeMethods => "tymethods", + Self::Methods => "methods", + Self::StructFields => "fields", + Self::Variants => "variants", + Self::Macros => "macros", + Self::PrimitiveTypes => "primitives", + Self::AssociatedTypes => "associated-types", + Self::AssociatedConstants => "associated-consts", + Self::ForeignTypes => "foreign-types", + Self::Keywords => "keywords", + Self::OpaqueTypes => "opaque-types", + Self::AttributeMacros => "attributes", + Self::DeriveMacros => "derives", + Self::TraitAliases => "trait-aliases", + } + } + + fn name(self) -> &'static str { + match self { + Self::Reexports => "Re-exports", + Self::Modules => "Modules", + Self::Structs => "Structs", + Self::Unions => "Unions", + Self::Enums => "Enums", + Self::Functions => "Functions", + Self::TypeDefinitions => "Type Definitions", + Self::Statics => "Statics", + Self::Constants => "Constants", + Self::Traits => "Traits", + Self::Implementations => "Implementations", + Self::TypeMethods => "Type Methods", + Self::Methods => "Methods", + Self::StructFields => "Struct Fields", + Self::Variants => "Variants", + Self::Macros => "Macros", + Self::PrimitiveTypes => "Primitive Types", + Self::AssociatedTypes => "Associated Types", + Self::AssociatedConstants => "Associated Constants", + Self::ForeignTypes => "Foreign Types", + Self::Keywords => "Keywords", + Self::OpaqueTypes => "Opaque Types", + Self::AttributeMacros => "Attribute Macros", + Self::DeriveMacros => "Derive Macros", + Self::TraitAliases => "Trait aliases", + } + } +} + +fn item_ty_to_section(ty: ItemType) -> ItemSection { match ty { - ItemType::ExternCrate | ItemType::Import => ("reexports", "Re-exports"), - ItemType::Module => ("modules", "Modules"), - ItemType::Struct => ("structs", "Structs"), - ItemType::Union => ("unions", "Unions"), - ItemType::Enum => ("enums", "Enums"), - ItemType::Function => ("functions", "Functions"), - ItemType::Typedef => ("types", "Type Definitions"), - ItemType::Static => ("statics", "Statics"), - ItemType::Constant => ("constants", "Constants"), - ItemType::Trait => ("traits", "Traits"), - ItemType::Impl => ("impls", "Implementations"), - ItemType::TyMethod => ("tymethods", "Type Methods"), - ItemType::Method => ("methods", "Methods"), - ItemType::StructField => ("fields", "Struct Fields"), - ItemType::Variant => ("variants", "Variants"), - ItemType::Macro => ("macros", "Macros"), - ItemType::Primitive => ("primitives", "Primitive Types"), - ItemType::AssocType => ("associated-types", "Associated Types"), - ItemType::AssocConst => ("associated-consts", "Associated Constants"), - ItemType::ForeignType => ("foreign-types", "Foreign Types"), - ItemType::Keyword => ("keywords", "Keywords"), - ItemType::OpaqueTy => ("opaque-types", "Opaque Types"), - ItemType::ProcAttribute => ("attributes", "Attribute Macros"), - ItemType::ProcDerive => ("derives", "Derive Macros"), - ItemType::TraitAlias => ("trait-aliases", "Trait aliases"), + ItemType::ExternCrate | ItemType::Import => ItemSection::Reexports, + ItemType::Module => ItemSection::Modules, + ItemType::Struct => ItemSection::Structs, + ItemType::Union => ItemSection::Unions, + ItemType::Enum => ItemSection::Enums, + ItemType::Function => ItemSection::Functions, + ItemType::Typedef => ItemSection::TypeDefinitions, + ItemType::Static => ItemSection::Statics, + ItemType::Constant => ItemSection::Constants, + ItemType::Trait => ItemSection::Traits, + ItemType::Impl => ItemSection::Implementations, + ItemType::TyMethod => ItemSection::TypeMethods, + ItemType::Method => ItemSection::Methods, + ItemType::StructField => ItemSection::StructFields, + ItemType::Variant => ItemSection::Variants, + ItemType::Macro => ItemSection::Macros, + ItemType::Primitive => ItemSection::PrimitiveTypes, + ItemType::AssocType => ItemSection::AssociatedTypes, + ItemType::AssocConst => ItemSection::AssociatedConstants, + ItemType::ForeignType => ItemSection::ForeignTypes, + ItemType::Keyword => ItemSection::Keywords, + ItemType::OpaqueTy => ItemSection::OpaqueTypes, + ItemType::ProcAttribute => ItemSection::AttributeMacros, + ItemType::ProcDerive => ItemSection::DeriveMacros, + ItemType::TraitAlias => ItemSection::TraitAliases, ItemType::Generic => unreachable!(), } } @@ -2449,8 +2540,8 @@ fn sidebar_module(buf: &mut Buffer, items: &[clean::Item]) { && (it.type_() == ItemType::ExternCrate || (it.type_() == ItemType::Import && !it.is_stripped())) }) { - let (id, name) = item_ty_to_strs(ItemType::Import); - sidebar.push_str(&format!("
  • {}
  • ", id, name)); + let sec = item_ty_to_section(ItemType::Import); + sidebar.push_str(&format!("
  • {}
  • ", sec.id(), sec.name())); } // ordering taken from item_module, reorder, where it prioritized elements in a certain order @@ -2478,8 +2569,8 @@ fn sidebar_module(buf: &mut Buffer, items: &[clean::Item]) { ItemType::Keyword, ] { if items.iter().any(|it| !it.is_stripped() && it.type_() == myty && it.name.is_some()) { - let (id, name) = item_ty_to_strs(myty); - sidebar.push_str(&format!("
  • {}
  • ", id, name)); + let sec = item_ty_to_section(myty); + sidebar.push_str(&format!("
  • {}
  • ", sec.id(), sec.name())); } } diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index f2c111495edfb..d73bc658f9fd3 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -16,10 +16,10 @@ use rustc_span::symbol::{kw, sym, Symbol}; use rustc_target::abi::{Layout, Primitive, TagEncoding, Variants}; use super::{ - collect_paths_for_type, document, ensure_trailing_slash, item_ty_to_strs, notable_traits_decl, - render_assoc_item, render_assoc_items, render_attributes_in_code, render_attributes_in_pre, - render_impl, render_stability_since_raw, write_srclink, AssocItemLink, Context, - ImplRenderingParameters, + collect_paths_for_type, document, ensure_trailing_slash, item_ty_to_section, + notable_traits_decl, render_assoc_item, render_assoc_items, render_attributes_in_code, + render_attributes_in_pre, render_impl, render_stability_since_raw, write_srclink, + AssocItemLink, Context, ImplRenderingParameters, }; use crate::clean; use crate::formats::item_type::ItemType; @@ -288,15 +288,15 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl w.write_str(ITEM_TABLE_CLOSE); } curty = myty; - let (short, name) = item_ty_to_strs(myty.unwrap()); + let sec = item_ty_to_section(myty.unwrap()); write!( w, "

    \ {name}\

    \n{}", ITEM_TABLE_OPEN, - id = cx.derive_id(short.to_owned()), - name = name + id = cx.derive_id(sec.id().to_owned()), + name = sec.name(), ); } From 1115f69bf4bc96201a130c876f1a2e866f58c907 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Fri, 7 Jan 2022 16:20:53 -0800 Subject: [PATCH 2/4] Deduplicate item sections --- src/librustdoc/html/render/mod.rs | 15 +++++---------- src/librustdoc/html/render/print_item.rs | 20 ++++++++------------ 2 files changed, 13 insertions(+), 22 deletions(-) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 3fd94fb9dc522..279047a2d1cc3 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -2534,19 +2534,11 @@ fn item_ty_to_section(ty: ItemType) -> ItemSection { fn sidebar_module(buf: &mut Buffer, items: &[clean::Item]) { let mut sidebar = String::new(); - // Re-exports are handled a bit differently because they can be extern crates or imports. - if items.iter().any(|it| { - it.name.is_some() - && (it.type_() == ItemType::ExternCrate - || (it.type_() == ItemType::Import && !it.is_stripped())) - }) { - let sec = item_ty_to_section(ItemType::Import); - sidebar.push_str(&format!("
  • {}
  • ", sec.id(), sec.name())); - } - + let mut already_emitted_sections = FxHashSet::default(); // ordering taken from item_module, reorder, where it prioritized elements in a certain order // to print its headings for &myty in &[ + ItemType::Import, ItemType::Primitive, ItemType::Module, ItemType::Macro, @@ -2570,6 +2562,9 @@ fn sidebar_module(buf: &mut Buffer, items: &[clean::Item]) { ] { if items.iter().any(|it| !it.is_stripped() && it.type_() == myty && it.name.is_some()) { let sec = item_ty_to_section(myty); + if !already_emitted_sections.insert(sec) { + continue; + } sidebar.push_str(&format!("
  • {}
  • ", sec.id(), sec.name())); } } diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index d73bc658f9fd3..e781e3c1ef476 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -271,7 +271,7 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl }); debug!("{:?}", indices); - let mut curty = None; + let mut last_section = None; for &idx in &indices { let myitem = &items[idx]; @@ -279,24 +279,20 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl continue; } - let myty = Some(myitem.type_()); - if curty == Some(ItemType::ExternCrate) && myty == Some(ItemType::Import) { - // Put `extern crate` and `use` re-exports in the same section. - curty = myty; - } else if myty != curty { - if curty.is_some() { + let my_section = item_ty_to_section(myitem.type_()); + if Some(my_section) != last_section { + if last_section.is_some() { w.write_str(ITEM_TABLE_CLOSE); } - curty = myty; - let sec = item_ty_to_section(myty.unwrap()); + last_section = Some(my_section); write!( w, "

    \ {name}\

    \n{}", ITEM_TABLE_OPEN, - id = cx.derive_id(sec.id().to_owned()), - name = sec.name(), + id = cx.derive_id(my_section.id().to_owned()), + name = my_section.name(), ); } @@ -408,7 +404,7 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl } } - if curty.is_some() { + if last_section.is_some() { w.write_str(ITEM_TABLE_CLOSE); } } From 163a8004ae61e0c1d35f6411d65868bc03556bf9 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Fri, 7 Jan 2022 16:30:01 -0800 Subject: [PATCH 3/4] Refactor sidebar printing code The new code is much simpler and easier to understand. In fact, the old code actually had a subtle bug where it excluded a few item types, including trait aliases, from the sidebar, even though they are rendered on the page itself! Now, all sections should show up in the sidebar. --- src/librustdoc/html/render/mod.rs | 84 +++++++++++++----------- src/librustdoc/html/render/print_item.rs | 4 +- 2 files changed, 48 insertions(+), 40 deletions(-) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 279047a2d1cc3..6dd730c3f8861 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -2412,22 +2412,22 @@ fn sidebar_enum(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, e: &clean: #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] enum ItemSection { Reexports, + PrimitiveTypes, Modules, + Macros, Structs, - Unions, Enums, - Functions, - TypeDefinitions, - Statics, Constants, + Statics, Traits, + Functions, + TypeDefinitions, + Unions, Implementations, TypeMethods, Methods, StructFields, Variants, - Macros, - PrimitiveTypes, AssociatedTypes, AssociatedConstants, ForeignTypes, @@ -2439,6 +2439,38 @@ enum ItemSection { } impl ItemSection { + const ALL: &'static [Self] = { + use ItemSection::*; + // NOTE: The order here affects the order in the UI. + &[ + Reexports, + PrimitiveTypes, + Modules, + Macros, + Structs, + Enums, + Constants, + Statics, + Traits, + Functions, + TypeDefinitions, + Unions, + Implementations, + TypeMethods, + Methods, + StructFields, + Variants, + AssociatedTypes, + AssociatedConstants, + ForeignTypes, + Keywords, + OpaqueTypes, + AttributeMacros, + DeriveMacros, + TraitAliases, + ] + }; + fn id(self) -> &'static str { match self { Self::Reexports => "reexports", @@ -2534,39 +2566,13 @@ fn item_ty_to_section(ty: ItemType) -> ItemSection { fn sidebar_module(buf: &mut Buffer, items: &[clean::Item]) { let mut sidebar = String::new(); - let mut already_emitted_sections = FxHashSet::default(); - // ordering taken from item_module, reorder, where it prioritized elements in a certain order - // to print its headings - for &myty in &[ - ItemType::Import, - ItemType::Primitive, - ItemType::Module, - ItemType::Macro, - ItemType::Struct, - ItemType::Enum, - ItemType::Constant, - ItemType::Static, - ItemType::Trait, - ItemType::Function, - ItemType::Typedef, - ItemType::Union, - ItemType::Impl, - ItemType::TyMethod, - ItemType::Method, - ItemType::StructField, - ItemType::Variant, - ItemType::AssocType, - ItemType::AssocConst, - ItemType::ForeignType, - ItemType::Keyword, - ] { - if items.iter().any(|it| !it.is_stripped() && it.type_() == myty && it.name.is_some()) { - let sec = item_ty_to_section(myty); - if !already_emitted_sections.insert(sec) { - continue; - } - sidebar.push_str(&format!("
  • {}
  • ", sec.id(), sec.name())); - } + let item_sections_in_use: FxHashSet<_> = items + .iter() + .filter(|it| !it.is_stripped() && it.name.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)) { + sidebar.push_str(&format!("
  • {}
  • ", sec.id(), sec.name())); } if !sidebar.is_empty() { diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index e781e3c1ef476..6e466ae8218c7 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -222,7 +222,9 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl ) -> Ordering { let ty1 = i1.type_(); let ty2 = i2.type_(); - if ty1 != ty2 { + if item_ty_to_section(ty1) != item_ty_to_section(ty2) + || (ty1 != ty2 && (ty1 == ItemType::ExternCrate || ty2 == ItemType::ExternCrate)) + { return (reorder(ty1), idx1).cmp(&(reorder(ty2), idx2)); } let s1 = i1.stability(tcx).as_ref().map(|s| s.level); From 504f3f037d6c42606740637eb711a891d071bf53 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Fri, 7 Jan 2022 15:30:50 -0800 Subject: [PATCH 4/4] Title-case trait aliases section for consistency --- src/librustdoc/html/render/mod.rs | 2 +- src/test/rustdoc/trait_alias.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 6dd730c3f8861..f3e46c93d2794 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -2527,7 +2527,7 @@ impl ItemSection { Self::OpaqueTypes => "Opaque Types", Self::AttributeMacros => "Attribute Macros", Self::DeriveMacros => "Derive Macros", - Self::TraitAliases => "Trait aliases", + Self::TraitAliases => "Trait Aliases", } } } diff --git a/src/test/rustdoc/trait_alias.rs b/src/test/rustdoc/trait_alias.rs index dec7fe3f6a5d9..a0c657d9a054d 100644 --- a/src/test/rustdoc/trait_alias.rs +++ b/src/test/rustdoc/trait_alias.rs @@ -8,7 +8,7 @@ use std::fmt::Debug; // @has foo/all.html '//a[@href="traitalias.Alias2.html"]' 'Alias2' // @has foo/all.html '//a[@href="traitalias.Foo.html"]' 'Foo' -// @has foo/index.html '//h2[@id="trait-aliases"]' 'Trait aliases' +// @has foo/index.html '//h2[@id="trait-aliases"]' 'Trait Aliases' // @has foo/index.html '//a[@class="traitalias"]' 'CopyAlias' // @has foo/index.html '//a[@class="traitalias"]' 'Alias2' // @has foo/index.html '//a[@class="traitalias"]' 'Foo'