diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 32e4a82918421..f3e46c93d2794 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -2409,33 +2409,156 @@ 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, + PrimitiveTypes, + Modules, + Macros, + Structs, + Enums, + Constants, + Statics, + Traits, + Functions, + TypeDefinitions, + Unions, + Implementations, + TypeMethods, + Methods, + StructFields, + Variants, + AssociatedTypes, + AssociatedConstants, + ForeignTypes, + Keywords, + OpaqueTypes, + AttributeMacros, + DeriveMacros, + TraitAliases, +} + +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", + 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!(), } } @@ -2443,44 +2566,13 @@ fn item_ty_to_strs(ty: ItemType) -> (&'static str, &'static str) { 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 (id, name) = item_ty_to_strs(ItemType::Import); - sidebar.push_str(&format!("
  • {}
  • ", id, name)); - } - - // ordering taken from item_module, reorder, where it prioritized elements in a certain order - // to print its headings - for &myty in &[ - 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 (id, name) = item_ty_to_strs(myty); - sidebar.push_str(&format!("
  • {}
  • ", id, 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 f2c111495edfb..6e466ae8218c7 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; @@ -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); @@ -271,7 +273,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 +281,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 (short, name) = item_ty_to_strs(myty.unwrap()); + last_section = Some(my_section); write!( w, "

    \ {name}\

    \n{}", ITEM_TABLE_OPEN, - id = cx.derive_id(short.to_owned()), - name = name + id = cx.derive_id(my_section.id().to_owned()), + name = my_section.name(), ); } @@ -408,7 +406,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); } } 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'