diff options
Diffstat (limited to 'src/librustdoc/html/render/print_item.rs')
-rw-r--r-- | src/librustdoc/html/render/print_item.rs | 449 |
1 files changed, 299 insertions, 150 deletions
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 6cab34986..c6751c958 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -198,7 +198,7 @@ pub(super) fn print_item( clean::StructItem(..) => "Struct ", clean::UnionItem(..) => "Union ", clean::EnumItem(..) => "Enum ", - clean::TypedefItem(..) => "Type Definition ", + clean::TypeAliasItem(..) => "Type Alias ", clean::MacroItem(..) => "Macro ", clean::ProcMacroItem(ref mac) => match mac.kind { MacroKind::Bang => "Macro ", @@ -273,7 +273,7 @@ pub(super) fn print_item( clean::StructItem(ref s) => item_struct(buf, cx, item, s), clean::UnionItem(ref s) => item_union(buf, cx, item, s), clean::EnumItem(ref e) => item_enum(buf, cx, item, e), - clean::TypedefItem(ref t) => item_typedef(buf, cx, item, t), + clean::TypeAliasItem(ref t) => item_type_alias(buf, cx, item, t), clean::MacroItem(ref m) => item_macro(buf, cx, item, m), clean::ProcMacroItem(ref m) => item_proc_macro(buf, cx, item, m), clean::PrimitiveItem(_) => item_primitive(buf, cx, item), @@ -343,7 +343,7 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items: ItemType::Static => 8, ItemType::Trait => 9, ItemType::Function => 10, - ItemType::Typedef => 12, + ItemType::TypeAlias => 12, ItemType::Union => 13, _ => 14 + ty as u8, } @@ -1217,8 +1217,8 @@ fn item_opaque_ty( .unwrap(); } -fn item_typedef(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::Typedef) { - fn write_content(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Typedef) { +fn item_type_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::TypeAlias) { + fn write_content(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::TypeAlias) { wrap_item(w, |w| { write!( w, @@ -1237,6 +1237,75 @@ fn item_typedef(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clea write!(w, "{}", document(cx, it, None, HeadingOffset::H2)); + if let Some(inner_type) = &t.inner_type { + write!( + w, + "<h2 id=\"aliased-type\" class=\"small-section-header\">\ + Aliased Type<a href=\"#aliased-type\" class=\"anchor\">§</a></h2>" + ); + + match inner_type { + clean::TypeAliasInnerType::Enum { variants, is_non_exhaustive } => { + let variants_iter = || variants.iter().filter(|i| !i.is_stripped()); + wrap_item(w, |w| { + let variants_len = variants.len(); + let variants_count = variants_iter().count(); + let has_stripped_entries = variants_len != variants_count; + + write!(w, "enum {}{}", it.name.unwrap(), t.generics.print(cx)); + render_enum_fields( + w, + cx, + Some(&t.generics), + variants_iter(), + variants_count, + has_stripped_entries, + *is_non_exhaustive, + ) + }); + item_variants(w, cx, it, variants_iter()); + } + clean::TypeAliasInnerType::Union { fields } => { + wrap_item(w, |w| { + let fields_count = fields.iter().filter(|i| !i.is_stripped()).count(); + let has_stripped_fields = fields.len() != fields_count; + + write!(w, "union {}{}", it.name.unwrap(), t.generics.print(cx)); + render_struct_fields( + w, + Some(&t.generics), + None, + fields, + "", + true, + has_stripped_fields, + cx, + ); + }); + item_fields(w, cx, it, fields, None); + } + clean::TypeAliasInnerType::Struct { ctor_kind, fields } => { + wrap_item(w, |w| { + let fields_count = fields.iter().filter(|i| !i.is_stripped()).count(); + let has_stripped_fields = fields.len() != fields_count; + + write!(w, "struct {}{}", it.name.unwrap(), t.generics.print(cx)); + render_struct_fields( + w, + Some(&t.generics), + *ctor_kind, + fields, + "", + true, + has_stripped_fields, + cx, + ); + }); + item_fields(w, cx, it, fields, None); + } + } + } + let def_id = it.item_id.expect_def_id(); // Render any items associated directly to this alias, as otherwise they // won't be visible anywhere in the docs. It would be nice to also show @@ -1315,6 +1384,12 @@ fn print_tuple_struct_fields<'a, 'cx: 'a>( s: &'a [clean::Item], ) -> impl fmt::Display + 'a + Captures<'cx> { display_fn(|f| { + if s.iter() + .all(|field| matches!(*field.kind, clean::StrippedItem(box clean::StructFieldItem(..)))) + { + return f.write_str("/* private fields */"); + } + for (i, ty) in s.iter().enumerate() { if i > 0 { f.write_str(", ")?; @@ -1332,7 +1407,7 @@ fn print_tuple_struct_fields<'a, 'cx: 'a>( fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::Enum) { let tcx = cx.tcx(); let count_variants = e.variants().count(); - wrap_item(w, |mut w| { + wrap_item(w, |w| { render_attributes_in_code(w, it, tcx); write!( w, @@ -1341,148 +1416,179 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean:: it.name.unwrap(), e.generics.print(cx), ); - if !print_where_clause_and_check(w, &e.generics, cx) { - // If there wasn't a `where` clause, we add a whitespace. - w.write_str(" "); - } + render_enum_fields( + w, + cx, + Some(&e.generics), + e.variants(), + count_variants, + e.has_stripped_entries(), + it.is_non_exhaustive(), + ); + }); - let variants_stripped = e.has_stripped_entries(); - if count_variants == 0 && !variants_stripped { - w.write_str("{}"); - } else { - w.write_str("{\n"); - let toggle = should_hide_fields(count_variants); - if toggle { - toggle_open(&mut w, format_args!("{count_variants} variants")); - } - for v in e.variants() { - w.write_str(" "); - let name = v.name.unwrap(); - match *v.kind { - // FIXME(#101337): Show discriminant - clean::VariantItem(ref var) => match var.kind { - clean::VariantKind::CLike => w.write_str(name.as_str()), - clean::VariantKind::Tuple(ref s) => { - write!(w, "{name}({})", print_tuple_struct_fields(cx, s),); - } - clean::VariantKind::Struct(ref s) => { - render_struct(w, v, None, None, &s.fields, " ", false, cx); - } - }, - _ => unreachable!(), - } - w.write_str(",\n"); - } + write!(w, "{}", document(cx, it, None, HeadingOffset::H2)); - if variants_stripped && !it.is_non_exhaustive() { - w.write_str(" // some variants omitted\n"); - } - if toggle { - toggle_close(&mut w); + if count_variants != 0 { + item_variants(w, cx, it, e.variants()); + } + let def_id = it.item_id.expect_def_id(); + write!(w, "{}", render_assoc_items(cx, it, def_id, AssocItemRender::All)); + write!(w, "{}", document_type_layout(cx, def_id)); +} + +fn render_enum_fields<'a>( + mut w: &mut Buffer, + cx: &mut Context<'_>, + g: Option<&clean::Generics>, + variants: impl Iterator<Item = &'a clean::Item>, + count_variants: usize, + has_stripped_entries: bool, + is_non_exhaustive: bool, +) { + if !g.is_some_and(|g| print_where_clause_and_check(w, g, cx)) { + // If there wasn't a `where` clause, we add a whitespace. + w.write_str(" "); + } + + let variants_stripped = has_stripped_entries; + if count_variants == 0 && !variants_stripped { + w.write_str("{}"); + } else { + w.write_str("{\n"); + let toggle = should_hide_fields(count_variants); + if toggle { + toggle_open(&mut w, format_args!("{count_variants} variants")); + } + const TAB: &str = " "; + for v in variants { + w.write_str(TAB); + let name = v.name.unwrap(); + match *v.kind { + // FIXME(#101337): Show discriminant + clean::VariantItem(ref var) => match var.kind { + clean::VariantKind::CLike => w.write_str(name.as_str()), + clean::VariantKind::Tuple(ref s) => { + write!(w, "{name}({})", print_tuple_struct_fields(cx, s),); + } + clean::VariantKind::Struct(ref s) => { + render_struct(w, v, None, None, &s.fields, TAB, false, cx); + } + }, + _ => unreachable!(), } - w.write_str("}"); + w.write_str(",\n"); } - }); - write!(w, "{}", document(cx, it, None, HeadingOffset::H2)); + if variants_stripped && !is_non_exhaustive { + w.write_str(" // some variants omitted\n"); + } + if toggle { + toggle_close(&mut w); + } + w.write_str("}"); + } +} - if count_variants != 0 { +fn item_variants<'a>( + w: &mut Buffer, + cx: &mut Context<'_>, + it: &clean::Item, + variants: impl Iterator<Item = &'a clean::Item>, +) { + let tcx = cx.tcx(); + write!( + w, + "<h2 id=\"variants\" class=\"variants small-section-header\">\ + Variants{}<a href=\"#variants\" class=\"anchor\">§</a>\ + </h2>\ + {}\ + <div class=\"variants\">", + document_non_exhaustive_header(it), + document_non_exhaustive(it) + ); + for variant in variants { + let id = cx.derive_id(format!("{}.{}", ItemType::Variant, variant.name.unwrap())); write!( w, - "<h2 id=\"variants\" class=\"variants small-section-header\">\ - Variants{}<a href=\"#variants\" class=\"anchor\">§</a>\ - </h2>\ - {}\ - <div class=\"variants\">", - document_non_exhaustive_header(it), - document_non_exhaustive(it) + "<section id=\"{id}\" class=\"variant\">\ + <a href=\"#{id}\" class=\"anchor\">§</a>", ); - for variant in e.variants() { - let id = cx.derive_id(format!("{}.{}", ItemType::Variant, variant.name.unwrap())); - write!( - w, - "<section id=\"{id}\" class=\"variant\">\ - <a href=\"#{id}\" class=\"anchor\">§</a>", - ); - render_stability_since_raw_with_extra( - w, - variant.stable_since(tcx), - variant.const_stability(tcx), - it.stable_since(tcx), - it.const_stable_since(tcx), - " rightside", - ); - write!(w, "<h3 class=\"code-header\">{name}", name = variant.name.unwrap()); + render_stability_since_raw_with_extra( + w, + variant.stable_since(tcx), + variant.const_stability(tcx), + it.stable_since(tcx), + it.const_stable_since(tcx), + " rightside", + ); + write!(w, "<h3 class=\"code-header\">{name}", name = variant.name.unwrap()); - let clean::VariantItem(variant_data) = &*variant.kind else { unreachable!() }; + let clean::VariantItem(variant_data) = &*variant.kind else { unreachable!() }; - if let clean::VariantKind::Tuple(ref s) = variant_data.kind { - write!(w, "({})", print_tuple_struct_fields(cx, s)); - } - w.write_str("</h3></section>"); - - let heading_and_fields = match &variant_data.kind { - clean::VariantKind::Struct(s) => Some(("Fields", &s.fields)), - clean::VariantKind::Tuple(fields) => { - // Documentation on tuple variant fields is rare, so to reduce noise we only emit - // the section if at least one field is documented. - if fields.iter().any(|f| !f.doc_value().is_empty()) { - Some(("Tuple Fields", fields)) - } else { - None - } + if let clean::VariantKind::Tuple(ref s) = variant_data.kind { + write!(w, "({})", print_tuple_struct_fields(cx, s)); + } + w.write_str("</h3></section>"); + + let heading_and_fields = match &variant_data.kind { + clean::VariantKind::Struct(s) => Some(("Fields", &s.fields)), + clean::VariantKind::Tuple(fields) => { + // Documentation on tuple variant fields is rare, so to reduce noise we only emit + // the section if at least one field is documented. + if fields.iter().any(|f| !f.doc_value().is_empty()) { + Some(("Tuple Fields", fields)) + } else { + None } - clean::VariantKind::CLike => None, - }; + } + clean::VariantKind::CLike => None, + }; - if let Some((heading, fields)) = heading_and_fields { - let variant_id = - cx.derive_id(format!("{}.{}.fields", ItemType::Variant, variant.name.unwrap())); - write!( - w, - "<div class=\"sub-variant\" id=\"{variant_id}\">\ - <h4>{heading}</h4>\ - {}", - document_non_exhaustive(variant) - ); - for field in fields { - match *field.kind { - clean::StrippedItem(box clean::StructFieldItem(_)) => {} - clean::StructFieldItem(ref ty) => { - let id = cx.derive_id(format!( - "variant.{}.field.{}", - variant.name.unwrap(), - field.name.unwrap() - )); - write!( - w, - "<div class=\"sub-variant-field\">\ + if let Some((heading, fields)) = heading_and_fields { + let variant_id = + cx.derive_id(format!("{}.{}.fields", ItemType::Variant, variant.name.unwrap())); + write!( + w, + "<div class=\"sub-variant\" id=\"{variant_id}\">\ + <h4>{heading}</h4>\ + {}", + document_non_exhaustive(variant) + ); + for field in fields { + match *field.kind { + clean::StrippedItem(box clean::StructFieldItem(_)) => {} + clean::StructFieldItem(ref ty) => { + let id = cx.derive_id(format!( + "variant.{}.field.{}", + variant.name.unwrap(), + field.name.unwrap() + )); + write!( + w, + "<div class=\"sub-variant-field\">\ <span id=\"{id}\" class=\"small-section-header\">\ <a href=\"#{id}\" class=\"anchor field\">§</a>\ <code>{f}: {t}</code>\ </span>", - f = field.name.unwrap(), - t = ty.print(cx), - ); - write!( - w, - "{}</div>", - document(cx, field, Some(variant), HeadingOffset::H5) - ); - } - _ => unreachable!(), + f = field.name.unwrap(), + t = ty.print(cx), + ); + write!( + w, + "{}</div>", + document(cx, field, Some(variant), HeadingOffset::H5) + ); } + _ => unreachable!(), } - w.write_str("</div>"); } - - write!(w, "{}", document(cx, variant, Some(it), HeadingOffset::H4)); + w.write_str("</div>"); } - write!(w, "</div>"); + + write!(w, "{}", document(cx, variant, Some(it), HeadingOffset::H4)); } - let def_id = it.item_id.expect_def_id(); - write!(w, "{}", render_assoc_items(cx, it, def_id, AssocItemRender::All)); - write!(w, "{}", document_type_layout(cx, def_id)); + write!(w, "</div>"); } fn item_macro(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::Macro) { @@ -1593,15 +1699,28 @@ fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean write!(w, "{}", document(cx, it, None, HeadingOffset::H2)); - let mut fields = s - .fields + item_fields(w, cx, it, &s.fields, s.ctor_kind); + + let def_id = it.item_id.expect_def_id(); + write!(w, "{}", render_assoc_items(cx, it, def_id, AssocItemRender::All)); + write!(w, "{}", document_type_layout(cx, def_id)); +} + +fn item_fields( + w: &mut Buffer, + cx: &mut Context<'_>, + it: &clean::Item, + fields: &Vec<clean::Item>, + ctor_kind: Option<CtorKind>, +) { + let mut fields = fields .iter() .filter_map(|f| match *f.kind { clean::StructFieldItem(ref ty) => Some((f, ty)), _ => None, }) .peekable(); - if let None | Some(CtorKind::Fn) = s.ctor_kind { + if let None | Some(CtorKind::Fn) = ctor_kind { if fields.peek().is_some() { write!( w, @@ -1609,7 +1728,7 @@ fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean {}{}<a href=\"#fields\" class=\"anchor\">§</a>\ </h2>\ {}", - if s.ctor_kind.is_none() { "Fields" } else { "Tuple Fields" }, + if ctor_kind.is_none() { "Fields" } else { "Tuple Fields" }, document_non_exhaustive_header(it), document_non_exhaustive(it) ); @@ -1630,9 +1749,6 @@ fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean } } } - let def_id = it.item_id.expect_def_id(); - write!(w, "{}", render_assoc_items(cx, it, def_id, AssocItemRender::All)); - write!(w, "{}", document_type_layout(cx, def_id)); } fn item_static(w: &mut impl fmt::Write, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Static) { @@ -1871,7 +1987,7 @@ fn render_union<'a, 'cx: 'a>( } fn render_struct( - mut w: &mut Buffer, + w: &mut Buffer, it: &clean::Item, g: Option<&clean::Generics>, ty: Option<CtorKind>, @@ -1891,6 +2007,29 @@ fn render_struct( if let Some(g) = g { write!(w, "{}", g.print(cx)) } + render_struct_fields( + w, + g, + ty, + fields, + tab, + structhead, + it.has_stripped_entries().unwrap_or(false), + cx, + ) +} + +fn render_struct_fields( + mut w: &mut Buffer, + g: Option<&clean::Generics>, + ty: Option<CtorKind>, + fields: &[clean::Item], + tab: &str, + structhead: bool, + has_stripped_entries: bool, + cx: &Context<'_>, +) { + let tcx = cx.tcx(); match ty { None => { let where_displayed = @@ -1922,11 +2061,11 @@ fn render_struct( } if has_visible_fields { - if it.has_stripped_entries().unwrap() { + if has_stripped_entries { write!(w, "\n{tab} /* private fields */"); } write!(w, "\n{tab}"); - } else if it.has_stripped_entries().unwrap() { + } else if has_stripped_entries { write!(w, " /* private fields */ "); } if toggle { @@ -1936,21 +2075,31 @@ fn render_struct( } Some(CtorKind::Fn) => { w.write_str("("); - for (i, field) in fields.iter().enumerate() { - if i > 0 { - w.write_str(", "); - } - match *field.kind { - clean::StrippedItem(box clean::StructFieldItem(..)) => write!(w, "_"), - clean::StructFieldItem(ref ty) => { - write!( - w, - "{}{}", - visibility_print_with_space(field.visibility(tcx), field.item_id, cx), - ty.print(cx), - ) + if fields.iter().all(|field| { + matches!(*field.kind, clean::StrippedItem(box clean::StructFieldItem(..))) + }) { + write!(w, "/* private fields */"); + } else { + for (i, field) in fields.iter().enumerate() { + if i > 0 { + w.write_str(", "); + } + match *field.kind { + clean::StrippedItem(box clean::StructFieldItem(..)) => write!(w, "_"), + clean::StructFieldItem(ref ty) => { + write!( + w, + "{}{}", + visibility_print_with_space( + field.visibility(tcx), + field.item_id, + cx + ), + ty.print(cx), + ) + } + _ => unreachable!(), } - _ => unreachable!(), } } w.write_str(")"); |