diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index f7073a8751f..552958d5e40 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -1,6 +1,7 @@ use clean::AttributesExt; use std::cmp::Ordering; +use std::fmt; use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; @@ -155,7 +156,7 @@ fn should_hide_fields(n_fields: usize) -> bool { n_fields > 12 } -fn toggle_open(w: &mut Buffer, text: &str) { +fn toggle_open(w: &mut Buffer, text: impl fmt::Display) { write!( w, "
\ @@ -481,6 +482,9 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra let consts = t.items.iter().filter(|m| m.is_associated_const()).collect::>(); let required = t.items.iter().filter(|m| m.is_ty_method()).collect::>(); let provided = t.items.iter().filter(|m| m.is_method()).collect::>(); + let count_types = types.len(); + let count_consts = consts.len(); + let count_methods = required.len() + provided.len(); // Output the trait definition wrap_into_docblock(w, |w| { @@ -511,9 +515,12 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra let mut toggle = false; // If there are too many associated types, hide _everything_ - if should_hide_fields(types.len()) { + if should_hide_fields(count_types) { toggle = true; - toggle_open(w, "associated items"); + toggle_open( + w, + format_args!("{} associated items", count_types + count_consts + count_methods), + ); } for t in &types { render_assoc_item(w, t, AssocItemLink::Anchor(None), ItemType::Trait, cx); @@ -523,9 +530,18 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra // We also do this if the types + consts is large because otherwise we could // render a bunch of types and _then_ a bunch of consts just because both were // _just_ under the limit - if !toggle && should_hide_fields(types.len() + consts.len()) { + if !toggle && should_hide_fields(count_types + count_consts) { toggle = true; - toggle_open(w, "associated constants and methods"); + toggle_open( + w, + format_args!( + "{} associated constant{} and {} method{}", + count_consts, + pluralize(count_consts), + count_methods, + pluralize(count_methods), + ), + ); } if !types.is_empty() && !consts.is_empty() { w.write_str("\n"); @@ -534,9 +550,9 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra render_assoc_item(w, t, AssocItemLink::Anchor(None), ItemType::Trait, cx); w.write_str(";\n"); } - if !toggle && should_hide_fields(required.len() + provided.len()) { + if !toggle && should_hide_fields(count_methods) { toggle = true; - toggle_open(w, "methods"); + toggle_open(w, format_args!("{} methods", count_methods)); } if !consts.is_empty() && !required.is_empty() { w.write_str("\n"); @@ -933,9 +949,10 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum w.write_str(" {}"); } else { w.write_str(" {\n"); - let toggle = should_hide_fields(e.variants.len()); + let count_variants = e.variants.len(); + let toggle = should_hide_fields(count_variants); if toggle { - toggle_open(w, "variants"); + toggle_open(w, format_args!("{} variants", count_variants)); } for v in &e.variants { w.write_str(" "); @@ -1012,7 +1029,8 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum use crate::clean::Variant; if let clean::VariantItem(Variant::Struct(ref s)) = *variant.kind { - toggle_open(w, "fields"); + let count_fields = s.fields.len(); + toggle_open(w, format_args!("{} field{}", count_fields, pluralize(count_fields))); let variant_id = cx.derive_id(format!( "{}.{}.fields", ItemType::Variant, @@ -1385,7 +1403,7 @@ fn render_union( fields.iter().filter(|f| matches!(*f.kind, clean::StructFieldItem(..))).count(); let toggle = should_hide_fields(count_fields); if toggle { - toggle_open(w, "fields"); + toggle_open(w, format_args!("{} fields", count_fields)); } for field in fields { @@ -1441,7 +1459,7 @@ fn render_struct( let has_visible_fields = count_fields > 0; let toggle = should_hide_fields(count_fields); if toggle { - toggle_open(w, "fields"); + toggle_open(w, format_args!("{} fields", count_fields)); } for field in fields { if let clean::StructFieldItem(ref ty) = *field.kind { @@ -1618,3 +1636,7 @@ fn document_type_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) { writeln!(w, ""); } + +fn pluralize(count: usize) -> &'static str { + if count > 1 { "s" } else { "" } +} diff --git a/src/test/rustdoc/toggle-item-contents.rs b/src/test/rustdoc/toggle-item-contents.rs index 6e3c0b4c681..167858b6065 100644 --- a/src/test/rustdoc/toggle-item-contents.rs +++ b/src/test/rustdoc/toggle-item-contents.rs @@ -9,7 +9,7 @@ pub struct PubStruct { // @has 'toggle_item_contents/struct.BigPubStruct.html' // @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1 -// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show fields' +// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 13 fields' pub struct BigPubStruct { pub a: usize, pub b: usize, @@ -28,7 +28,7 @@ pub struct BigPubStruct { // @has 'toggle_item_contents/union.BigUnion.html' // @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1 -// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show fields' +// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 13 fields' pub union BigUnion { pub a: usize, pub b: usize, @@ -63,7 +63,7 @@ pub struct PrivStruct { // @has 'toggle_item_contents/enum.Enum.html' // @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1 -// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show fields' +// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 2 fields' pub enum Enum { A, B, C, D { @@ -72,9 +72,19 @@ pub enum Enum { } } +// @has 'toggle_item_contents/enum.EnumStructVariant.html' +// @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1 +// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 1 field' +pub enum EnumStructVariant { + A, B, C, + D { + a: u8, + } +} + // @has 'toggle_item_contents/enum.LargeEnum.html' // @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1 -// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show variants' +// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 13 variants' pub enum LargeEnum { A, B, C, D, E, F(u8), G, H, I, J, K, L, M } @@ -90,7 +100,7 @@ pub trait Trait { // @has 'toggle_item_contents/trait.GinormousTrait.html' // @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1 -// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show associated items' +// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 16 associated items' pub trait GinormousTrait { type A; type B; @@ -113,7 +123,7 @@ pub trait GinormousTrait { // @has 'toggle_item_contents/trait.HugeTrait.html' // @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1 -// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show associated constants and methods' +// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 12 associated constants and 2 methods' pub trait HugeTrait { type A; const M: usize = 1; @@ -133,9 +143,30 @@ pub trait HugeTrait { fn bar(); } +// @has 'toggle_item_contents/trait.GiganticTrait.html' +// @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1 +// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 1 associated constant and 1 method' +pub trait GiganticTrait { + type A; + type B; + type C; + type D; + type E; + type F; + type G; + type H; + type I; + type J; + type K; + type L; + const M: usize = 1; + #[must_use] + fn foo(); +} + // @has 'toggle_item_contents/trait.BigTrait.html' // @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1 -// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show methods' +// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 14 methods' pub trait BigTrait { type A; #[must_use]