@@ -11,8 +11,8 @@ use rustc_span::symbol::{kw, sym, Symbol};
1111
1212use super :: {
1313 collect_paths_for_type, document, ensure_trailing_slash, item_ty_to_strs, notable_traits_decl,
14- render_assoc_item, render_assoc_items, render_attributes , render_impl ,
15- render_stability_since_raw, write_srclink, AssocItemLink , Context ,
14+ render_assoc_item, render_assoc_items, render_attributes_in_code , render_attributes_in_pre ,
15+ render_impl , render_stability_since_raw, write_srclink, AssocItemLink , Context ,
1616} ;
1717use crate :: clean:: { self , GetDefId } ;
1818use crate :: formats:: cache:: Cache ;
@@ -131,6 +131,26 @@ pub(super) fn print_item(cx: &Context<'_>, item: &clean::Item, buf: &mut Buffer)
131131 }
132132}
133133
134+ /// For large structs, enums, unions, etc, determine whether to hide their fields
135+ fn should_hide_fields ( n_fields : usize ) -> bool {
136+ n_fields > 12
137+ }
138+
139+ fn toggle_open ( w : & mut Buffer , text : & str ) {
140+ write ! (
141+ w,
142+ "<details class=\" rustdoc-toggle type-contents-toggle\" >\
143+ <summary class=\" hideme\" >\
144+ <span>Show {}</span>\
145+ </summary>",
146+ text
147+ ) ;
148+ }
149+
150+ fn toggle_close ( w : & mut Buffer ) {
151+ w. write_str ( "</details>" ) ;
152+ }
153+
134154fn item_module ( w : & mut Buffer , cx : & Context < ' _ > , item : & clean:: Item , items : & [ clean:: Item ] ) {
135155 document ( w, cx, item, None ) ;
136156
@@ -377,7 +397,7 @@ fn item_function(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, f: &clean::
377397 )
378398 . len ( ) ;
379399 w. write_str ( "<pre class=\" rust fn\" >" ) ;
380- render_attributes ( w, it, false ) ;
400+ render_attributes_in_pre ( w, it, "" ) ;
381401 write ! (
382402 w,
383403 "{vis}{constness}{asyncness}{unsafety}{abi}fn \
@@ -406,7 +426,7 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
406426 // Output the trait definition
407427 wrap_into_docblock ( w, |w| {
408428 w. write_str ( "<pre class=\" rust trait\" >" ) ;
409- render_attributes ( w, it, true ) ;
429+ render_attributes_in_pre ( w, it, "" ) ;
410430 write ! (
411431 w,
412432 "{}{}{}trait {}{}{}" ,
@@ -429,17 +449,36 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
429449 } else {
430450 // FIXME: we should be using a derived_id for the Anchors here
431451 w. write_str ( "{\n " ) ;
452+ let mut toggle = false ;
453+
454+ // If there are too many associated types, hide _everything_
455+ if should_hide_fields ( types. len ( ) ) {
456+ toggle = true ;
457+ toggle_open ( w, "associated items" ) ;
458+ }
432459 for t in & types {
433460 render_assoc_item ( w, t, AssocItemLink :: Anchor ( None ) , ItemType :: Trait , cx) ;
434461 w. write_str ( ";\n " ) ;
435462 }
463+ // If there are too many associated constants, hide everything after them
464+ // We also do this if the types + consts is large because otherwise we could
465+ // render a bunch of types and _then_ a bunch of consts just because both were
466+ // _just_ under the limit
467+ if !toggle && should_hide_fields ( types. len ( ) + consts. len ( ) ) {
468+ toggle = true ;
469+ toggle_open ( w, "associated constants and methods" ) ;
470+ }
436471 if !types. is_empty ( ) && !consts. is_empty ( ) {
437472 w. write_str ( "\n " ) ;
438473 }
439474 for t in & consts {
440475 render_assoc_item ( w, t, AssocItemLink :: Anchor ( None ) , ItemType :: Trait , cx) ;
441476 w. write_str ( ";\n " ) ;
442477 }
478+ if !toggle && should_hide_fields ( required. len ( ) + provided. len ( ) ) {
479+ toggle = true ;
480+ toggle_open ( w, "methods" ) ;
481+ }
443482 if !consts. is_empty ( ) && !required. is_empty ( ) {
444483 w. write_str ( "\n " ) ;
445484 }
@@ -470,6 +509,9 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
470509 w. write_str ( "<div class=\" item-spacer\" ></div>" ) ;
471510 }
472511 }
512+ if toggle {
513+ toggle_close ( w) ;
514+ }
473515 w. write_str ( "}" ) ;
474516 }
475517 w. write_str ( "</pre>" )
@@ -693,7 +735,7 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
693735
694736fn item_trait_alias ( w : & mut Buffer , cx : & Context < ' _ > , it : & clean:: Item , t : & clean:: TraitAlias ) {
695737 w. write_str ( "<pre class=\" rust trait-alias\" >" ) ;
696- render_attributes ( w, it, false ) ;
738+ render_attributes_in_pre ( w, it, "" ) ;
697739 write ! (
698740 w,
699741 "trait {}{}{} = {};</pre>" ,
@@ -714,7 +756,7 @@ fn item_trait_alias(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clea
714756
715757fn item_opaque_ty ( w : & mut Buffer , cx : & Context < ' _ > , it : & clean:: Item , t : & clean:: OpaqueTy ) {
716758 w. write_str ( "<pre class=\" rust opaque\" >" ) ;
717- render_attributes ( w, it, false ) ;
759+ render_attributes_in_pre ( w, it, "" ) ;
718760 write ! (
719761 w,
720762 "type {}{}{where_clause} = impl {bounds};</pre>" ,
@@ -735,7 +777,7 @@ fn item_opaque_ty(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean:
735777
736778fn item_typedef ( w : & mut Buffer , cx : & Context < ' _ > , it : & clean:: Item , t : & clean:: Typedef ) {
737779 w. write_str ( "<pre class=\" rust typedef\" >" ) ;
738- render_attributes ( w, it, false ) ;
780+ render_attributes_in_pre ( w, it, "" ) ;
739781 write ! (
740782 w,
741783 "type {}{}{where_clause} = {type_};</pre>" ,
@@ -757,7 +799,7 @@ fn item_typedef(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::T
757799fn item_union ( w : & mut Buffer , cx : & Context < ' _ > , it : & clean:: Item , s : & clean:: Union ) {
758800 wrap_into_docblock ( w, |w| {
759801 w. write_str ( "<pre class=\" rust union\" >" ) ;
760- render_attributes ( w, it, true ) ;
802+ render_attributes_in_pre ( w, it, "" ) ;
761803 render_union ( w, it, Some ( & s. generics ) , & s. fields , "" , true , cx) ;
762804 w. write_str ( "</pre>" )
763805 } ) ;
@@ -803,7 +845,7 @@ fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Uni
803845fn item_enum ( w : & mut Buffer , cx : & Context < ' _ > , it : & clean:: Item , e : & clean:: Enum ) {
804846 wrap_into_docblock ( w, |w| {
805847 w. write_str ( "<pre class=\" rust enum\" >" ) ;
806- render_attributes ( w, it, true ) ;
848+ render_attributes_in_pre ( w, it, "" ) ;
807849 write ! (
808850 w,
809851 "{}enum {}{}{}" ,
@@ -816,6 +858,10 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
816858 w. write_str ( " {}" ) ;
817859 } else {
818860 w. write_str ( " {\n " ) ;
861+ let toggle = should_hide_fields ( e. variants . len ( ) ) ;
862+ if toggle {
863+ toggle_open ( w, "variants" ) ;
864+ }
819865 for v in & e. variants {
820866 w. write_str ( " " ) ;
821867 let name = v. name . as_ref ( ) . unwrap ( ) ;
@@ -844,6 +890,9 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
844890 if e. variants_stripped {
845891 w. write_str ( " // some variants omitted\n " ) ;
846892 }
893+ if toggle {
894+ toggle_close ( w) ;
895+ }
847896 w. write_str ( "}" ) ;
848897 }
849898 w. write_str ( "</pre>" )
@@ -976,7 +1025,7 @@ fn item_primitive(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) {
9761025
9771026fn item_constant ( w : & mut Buffer , cx : & Context < ' _ > , it : & clean:: Item , c : & clean:: Constant ) {
9781027 w. write_str ( "<pre class=\" rust const\" >" ) ;
979- render_attributes ( w, it, false ) ;
1028+ render_attributes_in_code ( w, it) ;
9801029
9811030 write ! (
9821031 w,
@@ -1015,7 +1064,7 @@ fn item_constant(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, c: &clean::
10151064fn item_struct ( w : & mut Buffer , cx : & Context < ' _ > , it : & clean:: Item , s : & clean:: Struct ) {
10161065 wrap_into_docblock ( w, |w| {
10171066 w. write_str ( "<pre class=\" rust struct\" >" ) ;
1018- render_attributes ( w, it, true ) ;
1067+ render_attributes_in_code ( w, it) ;
10191068 render_struct ( w, it, Some ( & s. generics ) , s. struct_type , & s. fields , "" , true , cx) ;
10201069 w. write_str ( "</pre>" )
10211070 } ) ;
@@ -1064,7 +1113,7 @@ fn item_struct(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St
10641113
10651114fn item_static ( w : & mut Buffer , cx : & Context < ' _ > , it : & clean:: Item , s : & clean:: Static ) {
10661115 w. write_str ( "<pre class=\" rust static\" >" ) ;
1067- render_attributes ( w, it, false ) ;
1116+ render_attributes_in_code ( w, it) ;
10681117 write ! (
10691118 w,
10701119 "{vis}static {mutability}{name}: {typ}</pre>" ,
@@ -1078,7 +1127,7 @@ fn item_static(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St
10781127
10791128fn item_foreign_type ( w : & mut Buffer , cx : & Context < ' _ > , it : & clean:: Item ) {
10801129 w. write_str ( "<pre class=\" rust foreigntype\" >extern {\n " ) ;
1081- render_attributes ( w, it, false ) ;
1130+ render_attributes_in_code ( w, it) ;
10821131 write ! (
10831132 w,
10841133 " {}type {};\n }}</pre>" ,
@@ -1171,7 +1220,7 @@ fn wrap_into_docblock<F>(w: &mut Buffer, f: F)
11711220where
11721221 F : FnOnce ( & mut Buffer ) ,
11731222{
1174- w. write_str ( "<div class=\" docblock type-decl hidden-by-usual-hider \" >" ) ;
1223+ w. write_str ( "<div class=\" docblock type-decl\" >" ) ;
11751224 f ( w) ;
11761225 w. write_str ( "</div>" )
11771226}
@@ -1261,6 +1310,13 @@ fn render_union(
12611310 }
12621311
12631312 write ! ( w, " {{\n {}" , tab) ;
1313+ let count_fields =
1314+ fields. iter ( ) . filter ( |f| matches ! ( * f. kind, clean:: StructFieldItem ( ..) ) ) . count ( ) ;
1315+ let toggle = should_hide_fields ( count_fields) ;
1316+ if toggle {
1317+ toggle_open ( w, "fields" ) ;
1318+ }
1319+
12641320 for field in fields {
12651321 if let clean:: StructFieldItem ( ref ty) = * field. kind {
12661322 write ! (
@@ -1277,6 +1333,9 @@ fn render_union(
12771333 if it. has_stripped_fields ( ) . unwrap ( ) {
12781334 write ! ( w, " // some fields omitted\n {}" , tab) ;
12791335 }
1336+ if toggle {
1337+ toggle_close ( w) ;
1338+ }
12801339 w. write_str ( "}" ) ;
12811340}
12821341
@@ -1305,8 +1364,14 @@ fn render_struct(
13051364 if let Some ( g) = g {
13061365 write ! ( w, "{}" , print_where_clause( g, cx. cache( ) , cx. tcx( ) , 0 , true ) , )
13071366 }
1308- let mut has_visible_fields = false ;
13091367 w. write_str ( " {" ) ;
1368+ let count_fields =
1369+ fields. iter ( ) . filter ( |f| matches ! ( * f. kind, clean:: StructFieldItem ( ..) ) ) . count ( ) ;
1370+ let has_visible_fields = count_fields > 0 ;
1371+ let toggle = should_hide_fields ( count_fields) ;
1372+ if toggle {
1373+ toggle_open ( w, "fields" ) ;
1374+ }
13101375 for field in fields {
13111376 if let clean:: StructFieldItem ( ref ty) = * field. kind {
13121377 write ! (
@@ -1317,7 +1382,6 @@ fn render_struct(
13171382 field. name. as_ref( ) . unwrap( ) ,
13181383 ty. print( cx. cache( ) , cx. tcx( ) ) ,
13191384 ) ;
1320- has_visible_fields = true ;
13211385 }
13221386 }
13231387
@@ -1331,6 +1395,9 @@ fn render_struct(
13311395 // `{ /* fields omitted */ }` to save space.
13321396 write ! ( w, " /* fields omitted */ " ) ;
13331397 }
1398+ if toggle {
1399+ toggle_close ( w) ;
1400+ }
13341401 w. write_str ( "}" ) ;
13351402 }
13361403 CtorKind :: Fn => {
0 commit comments