From eb2b7dcaa8a218bc10d7b938cd52634f578f002e Mon Sep 17 00:00:00 2001 From: Nicky Lim Date: Tue, 9 May 2023 00:01:30 +0800 Subject: [PATCH 01/13] Use `display_fn` for `render_attributes_in_code` --- src/librustdoc/html/render/mod.rs | 16 +++++++++++----- src/librustdoc/html/render/print_item.rs | 20 ++++++++++---------- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index e01341acf438e..75e6a746b8052 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -871,7 +871,7 @@ fn assoc_method( write!(w, "{}", render_attributes_in_pre(meth, indent_str, cx)); (4, indent_str, Ending::NoNewline) } else { - render_attributes_in_code(w, meth, cx); + write!(w, "{}", render_attributes_in_code(meth, tcx)); (0, "", Ending::Newline) }; w.reserve(header_len + "{".len() + "".len()); @@ -1075,10 +1075,16 @@ fn render_attributes_in_pre<'a, 'tcx: 'a>( // When an attribute is rendered inside a tag, it is formatted using // a div to produce a newline after it. -fn render_attributes_in_code(w: &mut impl fmt::Write, it: &clean::Item, cx: &Context<'_>) { - for attr in it.attributes(cx.tcx(), cx.cache(), false) { - write!(w, "
{attr}
").unwrap(); - } +fn render_attributes_in_code<'a, 'tcx>( + it: &'a clean::Item, + tcx: TyCtxt<'tcx>, +) -> impl fmt::Display + Captures<'a> + Captures<'tcx> { + display_fn(move |f| { + for a in it.attributes(tcx, false) { + write!(f, "
{}
", a)?; + } + Ok(()) + }) } #[derive(Copy, Clone)] diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index f6432dc61ae06..be94cd2bf1de3 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -1413,14 +1413,14 @@ 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, |w| { - render_attributes_in_code(w, it, cx); + wrap_item(w, |mut w| { write!( w, - "{}enum {}{}", + "{attrs}{}enum {}{}", visibility_print_with_space(it.visibility(tcx), it.item_id, cx), it.name.unwrap(), e.generics.print(cx), + attrs = render_attributes_in_code(it, tcx), ); render_enum_fields( @@ -1733,11 +1733,11 @@ fn item_primitive(w: &mut impl fmt::Write, cx: &mut Context<'_>, it: &clean::Ite fn item_constant(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, c: &clean::Constant) { wrap_item(w, |w| { let tcx = cx.tcx(); - render_attributes_in_code(w, it, cx); write!( w, - "{vis}const {name}{generics}: {typ}{where_clause}", + "{attrs}{vis}const {name}: {typ}", + attrs = render_attributes_in_code(it, tcx), vis = visibility_print_with_space(it.visibility(tcx), it.item_id, cx), name = it.name.unwrap(), generics = c.generics.print(cx), @@ -1782,7 +1782,7 @@ fn item_constant(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, c: &cle fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Struct) { wrap_item(w, |w| { - render_attributes_in_code(w, it, cx); + write!(w, "{}", render_attributes_in_code(it, cx.tcx())); render_struct(w, it, Some(&s.generics), s.ctor_kind, &s.fields, "", true, cx); }); @@ -1842,10 +1842,10 @@ fn item_fields( fn item_static(w: &mut impl fmt::Write, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Static) { wrap_item(w, |buffer| { - render_attributes_in_code(buffer, it, cx); write!( buffer, - "{vis}static {mutability}{name}: {typ}", + "{attrs}{vis}static {mutability}{name}: {typ}", + attrs = render_attributes_in_code(it, cx.tcx()), vis = visibility_print_with_space(it.visibility(cx.tcx()), it.item_id, cx), mutability = s.mutability.print_with_space(), name = it.name.unwrap(), @@ -1860,12 +1860,12 @@ fn item_static(w: &mut impl fmt::Write, cx: &mut Context<'_>, it: &clean::Item, fn item_foreign_type(w: &mut impl fmt::Write, cx: &mut Context<'_>, it: &clean::Item) { wrap_item(w, |buffer| { buffer.write_str("extern {\n").unwrap(); - render_attributes_in_code(buffer, it, cx); write!( buffer, - " {}type {};\n}}", + "{attrs} {}type {};\n}}", visibility_print_with_space(it.visibility(cx.tcx()), it.item_id, cx), it.name.unwrap(), + attrs = render_attributes_in_code(it, cx.tcx()), ) .unwrap(); }); From 8a81e1c1f4ae4f3cde5f1bab44f76e9a20226363 Mon Sep 17 00:00:00 2001 From: Nicky Lim Date: Wed, 10 May 2023 21:12:09 +0800 Subject: [PATCH 02/13] Use template struct for item_struct --- src/librustdoc/html/render/print_item.rs | 405 +++++++++++------- .../html/templates/item_struct.html | 8 + 2 files changed, 247 insertions(+), 166 deletions(-) create mode 100644 src/librustdoc/html/templates/item_struct.html diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index be94cd2bf1de3..effdcf7ccf801 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -1423,16 +1423,46 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean:: attrs = render_attributes_in_code(it, tcx), ); - render_enum_fields( - w, - cx, - Some(&e.generics), - &e.variants, - count_variants, - e.has_stripped_entries(), - it.is_non_exhaustive(), - it.def_id().unwrap(), - ); + 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!("{} variants", count_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 => write!(w, "{}", name), + clean::VariantKind::Tuple(ref s) => { + write!(w, "{name}({})", print_tuple_struct_fields(cx, s),); + } + clean::VariantKind::Struct(ref s) => { + write!( + w, + "{}", + render_struct(v, None, None, &s.fields, " ", false, cx) + ); + } + }, + _ => unreachable!(), + } + w.write_str(",\n"); + } + + if variants_stripped && !it.is_non_exhaustive() { + w.write_str(" // some variants omitted\n"); + } + if toggle { + toggle_close(&mut w); + } + w.write_str("}"); + } }); write!(w, "{}", document(cx, it, None, HeadingOffset::H2)); @@ -1781,63 +1811,123 @@ fn item_constant(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, c: &cle } fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Struct) { - wrap_item(w, |w| { - write!(w, "{}", render_attributes_in_code(it, cx.tcx())); - render_struct(w, it, Some(&s.generics), s.ctor_kind, &s.fields, "", true, cx); - }); + #[derive(Template)] + #[template(path = "item_struct.html")] + struct ItemStruct<'a, 'cx> { + cx: std::cell::RefCell<&'a mut Context<'cx>>, + it: &'a clean::Item, + s: &'a clean::Struct, + } - write!(w, "{}", document(cx, it, None, HeadingOffset::H2)); + impl<'a, 'cx: 'a> ItemStruct<'a, 'cx> { + fn render_attributes_in_code<'b>( + &'b self, + ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { + display_fn(move |f| { + let tcx = self.cx.borrow().tcx(); + write!(f, "{}", render_attributes_in_code(self.it, tcx)) + }) + } - item_fields(w, cx, it, &s.fields, s.ctor_kind); + fn render_struct<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { + display_fn(move |f| { + let cx = self.cx.borrow(); + let v = render_struct( + self.it, + Some(&self.s.generics), + self.s.ctor_kind, + &self.s.fields, + "", + true, + *cx, + ); + write!(f, "{v}") + }) + } - 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 document<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { + display_fn(move |f| { + let mut cx = self.cx.borrow_mut(); + let v = document(*cx, self.it, None, HeadingOffset::H2); + write!(f, "{v}") + }) + } -fn item_fields( - w: &mut Buffer, - cx: &mut Context<'_>, - it: &clean::Item, - fields: &Vec, - ctor_kind: Option, -) { - 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) = ctor_kind { - if fields.peek().is_some() { - write!( - w, - "

\ - {}{}§\ -

\ - {}", - if ctor_kind.is_none() { "Fields" } else { "Tuple Fields" }, - document_non_exhaustive_header(it), - document_non_exhaustive(it) - ); - for (index, (field, ty)) in fields.enumerate() { - let field_name = - field.name.map_or_else(|| index.to_string(), |sym| sym.as_str().to_string()); - let id = cx.derive_id(format!("{typ}.{field_name}", typ = ItemType::StructField)); - write!( - w, - "\ - §\ - {field_name}: {ty}\ - ", - item_type = ItemType::StructField, - ty = ty.print(cx) - ); - write!(w, "{}", document(cx, field, Some(it), HeadingOffset::H3)); - } + fn render_fields<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { + display_fn(move |f| { + let mut fields = self + .s + .fields + .iter() + .filter_map(|f| match *f.kind { + clean::StructFieldItem(ref ty) => Some((f, ty)), + _ => None, + }) + .peekable(); + if let None | Some(CtorKind::Fn) = self.s.ctor_kind { + if fields.peek().is_some() { + write!( + f, + "

\ + {}{}§\ +

\ + {}", + if self.s.ctor_kind.is_none() { "Fields" } else { "Tuple Fields" }, + document_non_exhaustive_header(self.it), + document_non_exhaustive(self.it) + )?; + let mut cx = self.cx.borrow_mut(); + for (index, (field, ty)) in fields.enumerate() { + let field_name = field + .name + .map_or_else(|| index.to_string(), |sym| sym.as_str().to_string()); + let id = + cx.derive_id(format!("{}.{}", ItemType::StructField, field_name)); + write!( + f, + "\ + §\ + {field_name}: {ty}\ + ", + ty = ty.print(*cx), + item_type = ItemType::StructField, + )?; + write!( + f, + "{doc}", + doc = document(*cx, field, Some(self.it), HeadingOffset::H3), + )?; + } + } + } + Ok(()) + }) + } + + fn render_assoc_items<'b>( + &'b self, + ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { + display_fn(move |f| { + let mut cx = self.cx.borrow_mut(); + let def_id = self.it.item_id.expect_def_id(); + let v = render_assoc_items(*cx, self.it, def_id, AssocItemRender::All); + write!(f, "{v}") + }) + } + + fn document_type_layout<'b>( + &'b self, + ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { + display_fn(move |f| { + let cx = self.cx.borrow(); + let def_id = self.it.item_id.expect_def_id(); + let v = document_type_layout(*cx, def_id); + write!(f, "{v}") + }) } } + + ItemStruct { cx: std::cell::RefCell::new(cx), it, s }.render_into(w).unwrap(); } fn item_static(w: &mut impl fmt::Write, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Static) { @@ -2075,109 +2165,91 @@ fn render_union<'a, 'cx: 'a>( }) } -fn render_struct( - w: &mut Buffer, - it: &clean::Item, - g: Option<&clean::Generics>, +fn render_struct<'a, 'cx: 'a>( + it: &'a clean::Item, + g: Option<&'a clean::Generics>, ty: Option, - fields: &[clean::Item], - tab: &str, + fields: &'a [clean::Item], + tab: &'a str, structhead: bool, - cx: &Context<'_>, -) { - let tcx = cx.tcx(); - write!( - w, - "{}{}{}", - visibility_print_with_space(it.visibility(tcx), it.item_id, cx), - if structhead { "struct " } else { "" }, - it.name.unwrap() - ); - 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, - ) -} + cx: &'a Context<'cx>, +) -> impl fmt::Display + 'a + Captures<'cx> { + display_fn(move |mut f| { + let tcx = cx.tcx(); + write!( + f, + "{}{}{}", + visibility_print_with_space(it.visibility(tcx), it.item_id, cx), + if structhead { "struct " } else { "" }, + it.name.unwrap() + )?; -fn render_struct_fields( - mut w: &mut Buffer, - g: Option<&clean::Generics>, - ty: Option, - fields: &[clean::Item], - tab: &str, - structhead: bool, - has_stripped_entries: bool, - cx: &Context<'_>, -) { - let tcx = cx.tcx(); - match ty { - None => { - let where_displayed = - g.map(|g| print_where_clause_and_check(w, g, cx)).unwrap_or(false); + if let Some(g) = g { + write!(f, "{}", g.print(cx))?; + } - // If there wasn't a `where` clause, we add a whitespace. - if !where_displayed { - w.write_str(" {"); - } else { - w.write_str("{"); - } - let count_fields = - fields.iter().filter(|f| matches!(*f.kind, clean::StructFieldItem(..))).count(); - let has_visible_fields = count_fields > 0; - let toggle = should_hide_fields(count_fields); - if toggle { - toggle_open(&mut w, format_args!("{count_fields} fields")); - } - for field in fields { - if let clean::StructFieldItem(ref ty) = *field.kind { - write!( - w, - "\n{tab} {vis}{name}: {ty},", - vis = visibility_print_with_space(field.visibility(tcx), field.item_id, cx), - name = field.name.unwrap(), - ty = ty.print(cx), - ); + match ty { + None => { + let mut buf = Buffer::html(); + let where_displayed = + g.map(|g| print_where_clause_and_check(&mut buf, g, cx)).unwrap_or(false); + write!(f, "{}", buf.into_inner())?; + + // If there wasn't a `where` clause, we add a whitespace. + if !where_displayed { + f.write_str(" {")?; + } else { + f.write_str("{")?; } - } - if has_visible_fields { - if has_stripped_entries { - write!(w, "\n{tab} /* private fields */"); + let count_fields = fields + .iter() + .filter(|item| matches!(*item.kind, clean::StructFieldItem(..))) + .count(); + let has_visible_fields = count_fields > 0; + let toggle = should_hide_fields(count_fields); + if toggle { + toggle_open(&mut f, format_args!("{} fields", count_fields)); } - write!(w, "\n{tab}"); - } else if has_stripped_entries { - write!(w, " /* private fields */ "); - } - if toggle { - toggle_close(&mut w); + for field in fields { + if let clean::StructFieldItem(ref ty) = *field.kind { + write!( + f, + "\n{} {}{}: {},", + tab, + visibility_print_with_space(field.visibility(tcx), field.item_id, cx), + field.name.unwrap(), + ty.print(cx), + )?; + } + } + + if has_visible_fields { + if it.has_stripped_entries().unwrap() { + write!(f, "\n{} /* private fields */", tab)?; + } + write!(f, "\n{}", tab)?; + } else if it.has_stripped_entries().unwrap() { + write!(f, " /* private fields */ ")?; + } + if toggle { + toggle_close(&mut f); + } + f.write_str("}")?; } - w.write_str("}"); - } - Some(CtorKind::Fn) => { - w.write_str("("); - if fields.iter().all(|field| { - matches!(*field.kind, clean::StrippedItem(box clean::StructFieldItem(..))) - }) { - write!(w, "/* private fields */"); - } else { + Some(CtorKind::Fn) => { + write!(f, "(")?; for (i, field) in fields.iter().enumerate() { if i > 0 { - w.write_str(", "); + write!(f, ", ")?; } match *field.kind { - clean::StrippedItem(box clean::StructFieldItem(..)) => write!(w, "_"), + clean::StrippedItem(box clean::StructFieldItem(..)) => { + write!(f, "_")?; + } clean::StructFieldItem(ref ty) => { write!( - w, + f, "{}{}", visibility_print_with_space( field.visibility(tcx), @@ -2185,29 +2257,30 @@ fn render_struct_fields( cx ), ty.print(cx), - ) + )?; } _ => unreachable!(), } } + write!(f, ")")?; + if let Some(g) = g { + write!(f, "{}", print_where_clause(g, cx, 0, Ending::NoNewline))?; + } + // We only want a ";" when we are displaying a tuple struct, not a variant tuple struct. + if structhead { + write!(f, ";")?; + } } - w.write_str(")"); - if let Some(g) = g { - write!(w, "{}", print_where_clause(g, cx, 0, Ending::NoNewline)); - } - // We only want a ";" when we are displaying a tuple struct, not a variant tuple struct. - if structhead { - w.write_str(";"); + Some(CtorKind::Const) => { + // Needed for PhantomData. + if let Some(g) = g { + write!(f, "{}", print_where_clause(g, cx, 0, Ending::NoNewline))?; + } + write!(f, ";")?; } } - Some(CtorKind::Const) => { - // Needed for PhantomData. - if let Some(g) = g { - write!(w, "{}", print_where_clause(g, cx, 0, Ending::NoNewline)); - } - w.write_str(";"); - } - } + Ok(()) + }) } fn document_non_exhaustive_header(item: &clean::Item) -> &str { diff --git a/src/librustdoc/html/templates/item_struct.html b/src/librustdoc/html/templates/item_struct.html new file mode 100644 index 0000000000000..686439f03fa89 --- /dev/null +++ b/src/librustdoc/html/templates/item_struct.html @@ -0,0 +1,8 @@ +

+    {{ self.render_attributes_in_code() | safe }}
+    {{ self.render_struct() | safe }}
+
+{{ self.document() | safe }} +{{ self.render_fields() | safe }} +{{ self.render_assoc_items() | safe }} +{{ self.document_type_layout() | safe }} From 483375867778fa75060325f1e1c51a07c7d7103f Mon Sep 17 00:00:00 2001 From: Nicky Lim Date: Fri, 12 May 2023 15:30:32 +0800 Subject: [PATCH 03/13] Expand `render_fields()` --- src/librustdoc/html/render/print_item.rs | 89 +++++++++---------- .../html/templates/item_struct.html | 16 +++- 2 files changed, 57 insertions(+), 48 deletions(-) diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index effdcf7ccf801..53796f505b58d 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -1853,54 +1853,49 @@ fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean }) } - fn render_fields<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { + fn fields(&self) -> impl Iterator { + self.s.fields.iter().filter_map(|item| match *item.kind { + clean::StructFieldItem(ref ty) => Some((item, ty)), + _ => None, + }) + } + + fn should_render_fields(&self) -> bool { + matches!(self.s.ctor_kind, None | Some(CtorKind::Fn)) + && self.fields().peekable().peek().is_some() + } + + fn document_non_exhaustive_header(&self) -> &str { + document_non_exhaustive_header(self.it) + } + + fn document_non_exhaustive(&self) -> impl fmt::Display + 'a { + document_non_exhaustive(self.it) + } + + fn render_field<'b>( + &'b self, + index: &'b usize, + field: &'b clean::Item, + ty: &'b clean::Type, + ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { display_fn(move |f| { - let mut fields = self - .s - .fields - .iter() - .filter_map(|f| match *f.kind { - clean::StructFieldItem(ref ty) => Some((f, ty)), - _ => None, - }) - .peekable(); - if let None | Some(CtorKind::Fn) = self.s.ctor_kind { - if fields.peek().is_some() { - write!( - f, - "

\ - {}{}§\ -

\ - {}", - if self.s.ctor_kind.is_none() { "Fields" } else { "Tuple Fields" }, - document_non_exhaustive_header(self.it), - document_non_exhaustive(self.it) - )?; - let mut cx = self.cx.borrow_mut(); - for (index, (field, ty)) in fields.enumerate() { - let field_name = field - .name - .map_or_else(|| index.to_string(), |sym| sym.as_str().to_string()); - let id = - cx.derive_id(format!("{}.{}", ItemType::StructField, field_name)); - write!( - f, - "\ - §\ - {field_name}: {ty}\ - ", - ty = ty.print(*cx), - item_type = ItemType::StructField, - )?; - write!( - f, - "{doc}", - doc = document(*cx, field, Some(self.it), HeadingOffset::H3), - )?; - } - } - } - Ok(()) + let mut cx = self.cx.borrow_mut(); + let field_name = + field.name.map_or_else(|| index.to_string(), |sym| sym.as_str().to_string()); + let id = cx.derive_id(format!("{}.{}", ItemType::StructField, field_name)); + write!( + f, + "\ + §\ + {field_name}: {ty}\ + ", + ty = ty.print(*cx), + item_type = ItemType::StructField, + )?; + + let v = document(*cx, field, Some(self.it), HeadingOffset::H3); + write!(f, "{v}") }) } diff --git a/src/librustdoc/html/templates/item_struct.html b/src/librustdoc/html/templates/item_struct.html index 686439f03fa89..de2a53dc349ea 100644 --- a/src/librustdoc/html/templates/item_struct.html +++ b/src/librustdoc/html/templates/item_struct.html @@ -3,6 +3,20 @@ {{ self.render_struct() | safe }}
{{ self.document() | safe }} -{{ self.render_fields() | safe }} +{% if self.should_render_fields() %} +

+ {% if self.s.ctor_kind.is_none() %} + Fields + {% else %} + Tuple Fields + {% endif %} + {{ self.document_non_exhaustive_header() | safe }} + § +

+ {{ self.document_non_exhaustive() | safe }} + {% for (index, (field, ty)) in self.fields().enumerate() %} + {{ self.render_field(index, field, ty) | safe }} + {% endfor %} +{% endif %} {{ self.render_assoc_items() | safe }} {{ self.document_type_layout() | safe }} From ca02fde4d8a45442c12417efea8c557a4849e71b Mon Sep 17 00:00:00 2001 From: Nicky Lim Date: Fri, 12 May 2023 15:47:20 +0800 Subject: [PATCH 04/13] Expand `render_field()` --- src/librustdoc/html/render/print_item.rs | 14 +++++++++++--- src/librustdoc/html/templates/item_struct.html | 3 ++- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 53796f505b58d..fd3e11047d8e3 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -1873,7 +1873,7 @@ fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean document_non_exhaustive(self.it) } - fn render_field<'b>( + fn render_field_in_span<'b>( &'b self, index: &'b usize, field: &'b clean::Item, @@ -1884,16 +1884,24 @@ fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean let field_name = field.name.map_or_else(|| index.to_string(), |sym| sym.as_str().to_string()); let id = cx.derive_id(format!("{}.{}", ItemType::StructField, field_name)); + let ty = ty.print(*cx); write!( f, "\ §\ {field_name}: {ty}\ ", - ty = ty.print(*cx), item_type = ItemType::StructField, - )?; + ) + }) + } + fn document_field<'b>( + &'b self, + field: &'b clean::Item, + ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { + display_fn(move |f| { + let mut cx = self.cx.borrow_mut(); let v = document(*cx, field, Some(self.it), HeadingOffset::H3); write!(f, "{v}") }) diff --git a/src/librustdoc/html/templates/item_struct.html b/src/librustdoc/html/templates/item_struct.html index de2a53dc349ea..967ad61eed572 100644 --- a/src/librustdoc/html/templates/item_struct.html +++ b/src/librustdoc/html/templates/item_struct.html @@ -15,7 +15,8 @@

{{ self.document_non_exhaustive() | safe }} {% for (index, (field, ty)) in self.fields().enumerate() %} - {{ self.render_field(index, field, ty) | safe }} + {{ self.render_field_in_span(index, field, ty) | safe }} + {{ self.document_field(field) | safe }} {% endfor %} {% endif %} {{ self.render_assoc_items() | safe }} From 631920266ed0dfc6c7992afb6d062379f2748577 Mon Sep 17 00:00:00 2001 From: Nicky Lim Date: Wed, 24 May 2023 18:14:57 +0800 Subject: [PATCH 05/13] Use functions instead of wrapping methods --- src/librustdoc/html/render/print_item.rs | 17 ----------------- src/librustdoc/html/templates/item_struct.html | 6 +++--- 2 files changed, 3 insertions(+), 20 deletions(-) diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index fd3e11047d8e3..0412f741e8dc2 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -1820,15 +1820,6 @@ fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean } impl<'a, 'cx: 'a> ItemStruct<'a, 'cx> { - fn render_attributes_in_code<'b>( - &'b self, - ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { - display_fn(move |f| { - let tcx = self.cx.borrow().tcx(); - write!(f, "{}", render_attributes_in_code(self.it, tcx)) - }) - } - fn render_struct<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { display_fn(move |f| { let cx = self.cx.borrow(); @@ -1865,14 +1856,6 @@ fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean && self.fields().peekable().peek().is_some() } - fn document_non_exhaustive_header(&self) -> &str { - document_non_exhaustive_header(self.it) - } - - fn document_non_exhaustive(&self) -> impl fmt::Display + 'a { - document_non_exhaustive(self.it) - } - fn render_field_in_span<'b>( &'b self, index: &'b usize, diff --git a/src/librustdoc/html/templates/item_struct.html b/src/librustdoc/html/templates/item_struct.html index 967ad61eed572..98773ee01a2d5 100644 --- a/src/librustdoc/html/templates/item_struct.html +++ b/src/librustdoc/html/templates/item_struct.html @@ -1,5 +1,5 @@

-    {{ self.render_attributes_in_code() | safe }}
+    {{ self::render_attributes_in_code(self.it, self.cx.borrow().tcx()) | safe }}
     {{ self.render_struct() | safe }}
 
{{ self.document() | safe }} @@ -10,10 +10,10 @@

{% else %} Tuple Fields {% endif %} - {{ self.document_non_exhaustive_header() | safe }} + {{ self::document_non_exhaustive_header(self.it) | safe }} §

- {{ self.document_non_exhaustive() | safe }} + {{ self::document_non_exhaustive(self.it) | safe }} {% for (index, (field, ty)) in self.fields().enumerate() %} {{ self.render_field_in_span(index, field, ty) | safe }} {{ self.document_field(field) | safe }} From 6a892f8a29875d8f98b4a39601e5d6766023650c Mon Sep 17 00:00:00 2001 From: Nicky Lim Date: Wed, 24 May 2023 18:32:13 +0800 Subject: [PATCH 06/13] Convert `should_render_fields` into a field --- src/librustdoc/html/render/print_item.rs | 32 +++++++++++-------- .../html/templates/item_struct.html | 4 +-- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 0412f741e8dc2..0d223b9b0d66b 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -1817,9 +1817,20 @@ fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean cx: std::cell::RefCell<&'a mut Context<'cx>>, it: &'a clean::Item, s: &'a clean::Struct, + should_render_fields: bool, } impl<'a, 'cx: 'a> ItemStruct<'a, 'cx> { + fn new( + cx: std::cell::RefCell<&'a mut Context<'cx>>, + it: &'a clean::Item, + s: &'a clean::Struct, + ) -> Self { + let should_render_fields = matches!(s.ctor_kind, None | Some(CtorKind::Fn)) + && struct_field_items(s).peekable().peek().is_some(); + Self { cx, it, s, should_render_fields } + } + fn render_struct<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { display_fn(move |f| { let cx = self.cx.borrow(); @@ -1844,18 +1855,6 @@ fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean }) } - fn fields(&self) -> impl Iterator { - self.s.fields.iter().filter_map(|item| match *item.kind { - clean::StructFieldItem(ref ty) => Some((item, ty)), - _ => None, - }) - } - - fn should_render_fields(&self) -> bool { - matches!(self.s.ctor_kind, None | Some(CtorKind::Fn)) - && self.fields().peekable().peek().is_some() - } - fn render_field_in_span<'b>( &'b self, index: &'b usize, @@ -1913,7 +1912,14 @@ fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean } } - ItemStruct { cx: std::cell::RefCell::new(cx), it, s }.render_into(w).unwrap(); + ItemStruct::new(std::cell::RefCell::new(cx), it, s).render_into(w).unwrap(); +} + +fn struct_field_items(s: &clean::Struct) -> impl Iterator { + s.fields.iter().filter_map(|item| match *item.kind { + clean::StructFieldItem(ref ty) => Some((item, ty)), + _ => None, + }) } fn item_static(w: &mut impl fmt::Write, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Static) { diff --git a/src/librustdoc/html/templates/item_struct.html b/src/librustdoc/html/templates/item_struct.html index 98773ee01a2d5..db9f3eda9156b 100644 --- a/src/librustdoc/html/templates/item_struct.html +++ b/src/librustdoc/html/templates/item_struct.html @@ -3,7 +3,7 @@ {{ self.render_struct() | safe }} {{ self.document() | safe }} -{% if self.should_render_fields() %} +{% if self.should_render_fields %}

{% if self.s.ctor_kind.is_none() %} Fields @@ -14,7 +14,7 @@

§

{{ self::document_non_exhaustive(self.it) | safe }} - {% for (index, (field, ty)) in self.fields().enumerate() %} + {% for (index, (field, ty)) in self::struct_field_items(self.s).enumerate() %} {{ self.render_field_in_span(index, field, ty) | safe }} {{ self.document_field(field) | safe }} {% endfor %} From 0fb10ab4e5df64b6484df26aab6deecbe9a2057f Mon Sep 17 00:00:00 2001 From: Nicky Lim Date: Wed, 24 May 2023 18:54:44 +0800 Subject: [PATCH 07/13] Fix borrowing errors --- src/librustdoc/html/render/print_item.rs | 9 +++++++++ src/librustdoc/html/templates/item_struct.html | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 0d223b9b0d66b..1096a8c674d36 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -1831,6 +1831,15 @@ fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean Self { cx, it, s, should_render_fields } } + fn render_attributes_in_code<'b>( + &'b self, + ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { + display_fn(move |f| { + let tcx = self.cx.borrow().tcx(); + write!(f, "{}", render_attributes_in_code(self.it, tcx)) + }) + } + fn render_struct<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { display_fn(move |f| { let cx = self.cx.borrow(); diff --git a/src/librustdoc/html/templates/item_struct.html b/src/librustdoc/html/templates/item_struct.html index db9f3eda9156b..5a78f44efac98 100644 --- a/src/librustdoc/html/templates/item_struct.html +++ b/src/librustdoc/html/templates/item_struct.html @@ -1,5 +1,5 @@

-    {{ self::render_attributes_in_code(self.it, self.cx.borrow().tcx()) | safe }}
+    {{ self.render_attributes_in_code() | safe }}
     {{ self.render_struct() | safe }}
 
{{ self.document() | safe }} From 97aca510732b41913d4c6b518876b735b579e27b Mon Sep 17 00:00:00 2001 From: Nicky Lim Date: Wed, 24 May 2023 22:04:38 +0800 Subject: [PATCH 08/13] Expand `render_field_in_span` in template --- src/librustdoc/html/render/print_item.rs | 33 +++++++++---------- .../html/templates/item_struct.html | 9 +++-- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 1096a8c674d36..b4c88f8b3b198 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -1820,6 +1820,13 @@ fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean should_render_fields: bool, } + struct Field<'a> { + item: &'a clean::Item, + name: String, + id: String, + ty: String, + } + impl<'a, 'cx: 'a> ItemStruct<'a, 'cx> { fn new( cx: std::cell::RefCell<&'a mut Context<'cx>>, @@ -1864,26 +1871,16 @@ fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean }) } - fn render_field_in_span<'b>( + fn struct_field_items_iter<'b>( &'b self, - index: &'b usize, - field: &'b clean::Item, - ty: &'b clean::Type, - ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { - display_fn(move |f| { + ) -> impl Iterator> + Captures<'a> + 'b + Captures<'cx> { + struct_field_items(self.s).enumerate().map(|(index, (item, ty))| { let mut cx = self.cx.borrow_mut(); - let field_name = - field.name.map_or_else(|| index.to_string(), |sym| sym.as_str().to_string()); - let id = cx.derive_id(format!("{}.{}", ItemType::StructField, field_name)); - let ty = ty.print(*cx); - write!( - f, - "\ - §\ - {field_name}: {ty}\ - ", - item_type = ItemType::StructField, - ) + let name = + item.name.map_or_else(|| index.to_string(), |sym| sym.as_str().to_string()); + let id = cx.derive_id(format!("{}.{}", ItemType::StructField, name)); + let ty = ty.print(*cx).to_string(); + Field { item, name, id, ty } }) } diff --git a/src/librustdoc/html/templates/item_struct.html b/src/librustdoc/html/templates/item_struct.html index 5a78f44efac98..22d7d1f66ceb5 100644 --- a/src/librustdoc/html/templates/item_struct.html +++ b/src/librustdoc/html/templates/item_struct.html @@ -14,9 +14,12 @@

§

{{ self::document_non_exhaustive(self.it) | safe }} - {% for (index, (field, ty)) in self::struct_field_items(self.s).enumerate() %} - {{ self.render_field_in_span(index, field, ty) | safe }} - {{ self.document_field(field) | safe }} + {% for field in self.struct_field_items_iter() %} + + § + {{ field.name|safe }}: {{~ field.ty|safe }} + + {{ self.document_field(field.item) | safe }} {% endfor %} {% endif %} {{ self.render_assoc_items() | safe }} From 1270d0060592b9824db5c29bad5766d4c0e26357 Mon Sep 17 00:00:00 2001 From: Nicky Lim Date: Mon, 29 May 2023 21:08:12 +0800 Subject: [PATCH 09/13] Use `ItemTemplate` trait --- src/librustdoc/html/render/print_item.rs | 98 +++++++++++-------- .../html/templates/item_struct.html | 8 +- 2 files changed, 63 insertions(+), 43 deletions(-) diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index b4c88f8b3b198..75a8dac1dd3ba 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -326,6 +326,59 @@ trait ItemTemplate<'a, 'cx: 'a>: askama::Template + fmt::Display { fn item_and_mut_cx(&self) -> (&'a clean::Item, RefMut<'_, &'a mut Context<'cx>>); } +fn item_template_document<'a: 'b, 'b, 'cx: 'a>( + templ: &'b impl ItemTemplate<'a, 'cx>, +) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { + display_fn(move |f| { + let (item, mut cx) = templ.item_and_mut_cx(); + let v = document(*cx, item, None, HeadingOffset::H2); + write!(f, "{v}") + }) +} + +fn item_template_document_type_layout<'a: 'b, 'b, 'cx: 'a>( + templ: &'b impl ItemTemplate<'a, 'cx>, +) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { + display_fn(move |f| { + let (item, cx) = templ.item_and_mut_cx(); + let def_id = item.item_id.expect_def_id(); + let v = document_type_layout(*cx, def_id); + write!(f, "{v}") + }) +} + +fn item_template_render_attributes_in_pre<'a: 'b, 'b, 'cx: 'a>( + templ: &'b impl ItemTemplate<'a, 'cx>, +) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { + display_fn(move |f| { + let (item, cx) = templ.item_and_mut_cx(); + let tcx = cx.tcx(); + let v = render_attributes_in_pre(item, "", tcx); + write!(f, "{v}") + }) +} + +fn item_template_render_attributes_in_code<'a: 'b, 'b, 'cx: 'a>( + templ: &'b impl ItemTemplate<'a, 'cx>, +) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { + display_fn(move |f| { + let (it, cx) = templ.item_and_mut_cx(); + let v = render_attributes_in_code(it, cx.tcx()); + write!(f, "{v}") + }) +} + +fn item_template_render_assoc_items<'a: 'b, 'b, 'cx: 'a>( + templ: &'b impl ItemTemplate<'a, 'cx>, +) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { + display_fn(move |f| { + let (item, mut cx) = templ.item_and_mut_cx(); + let def_id = item.item_id.expect_def_id(); + let v = render_assoc_items(*cx, item, def_id, AssocItemRender::All, None); + write!(f, "{v}") + }) +} + fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items: &[clean::Item]) { write!(w, "{}", document(cx, item, None, HeadingOffset::H2)); @@ -1827,6 +1880,12 @@ fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean ty: String, } + impl<'a, 'cx: 'a> ItemTemplate<'a, 'cx> for ItemStruct<'a, 'cx> { + fn item_and_mut_cx(&self) -> (&'a clean::Item, RefMut<'_, &'a mut Context<'cx>>) { + (self.it, self.cx.borrow_mut()) + } + } + impl<'a, 'cx: 'a> ItemStruct<'a, 'cx> { fn new( cx: std::cell::RefCell<&'a mut Context<'cx>>, @@ -1838,15 +1897,6 @@ fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean Self { cx, it, s, should_render_fields } } - fn render_attributes_in_code<'b>( - &'b self, - ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { - display_fn(move |f| { - let tcx = self.cx.borrow().tcx(); - write!(f, "{}", render_attributes_in_code(self.it, tcx)) - }) - } - fn render_struct<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { display_fn(move |f| { let cx = self.cx.borrow(); @@ -1863,14 +1913,6 @@ fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean }) } - fn document<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { - display_fn(move |f| { - let mut cx = self.cx.borrow_mut(); - let v = document(*cx, self.it, None, HeadingOffset::H2); - write!(f, "{v}") - }) - } - fn struct_field_items_iter<'b>( &'b self, ) -> impl Iterator> + Captures<'a> + 'b + Captures<'cx> { @@ -1894,28 +1936,6 @@ fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean write!(f, "{v}") }) } - - fn render_assoc_items<'b>( - &'b self, - ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { - display_fn(move |f| { - let mut cx = self.cx.borrow_mut(); - let def_id = self.it.item_id.expect_def_id(); - let v = render_assoc_items(*cx, self.it, def_id, AssocItemRender::All); - write!(f, "{v}") - }) - } - - fn document_type_layout<'b>( - &'b self, - ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { - display_fn(move |f| { - let cx = self.cx.borrow(); - let def_id = self.it.item_id.expect_def_id(); - let v = document_type_layout(*cx, def_id); - write!(f, "{v}") - }) - } } ItemStruct::new(std::cell::RefCell::new(cx), it, s).render_into(w).unwrap(); diff --git a/src/librustdoc/html/templates/item_struct.html b/src/librustdoc/html/templates/item_struct.html index 22d7d1f66ceb5..873bcc90687b6 100644 --- a/src/librustdoc/html/templates/item_struct.html +++ b/src/librustdoc/html/templates/item_struct.html @@ -1,8 +1,8 @@

-    {{ self.render_attributes_in_code() | safe }}
+    {{ self::item_template_render_attributes_in_code(self.borrow()) | safe }}
     {{ self.render_struct() | safe }}
 
-{{ self.document() | safe }} +{{ self::item_template_document(self.borrow()) | safe }} {% if self.should_render_fields %}

{% if self.s.ctor_kind.is_none() %} @@ -22,5 +22,5 @@

{{ self.document_field(field.item) | safe }} {% endfor %} {% endif %} -{{ self.render_assoc_items() | safe }} -{{ self.document_type_layout() | safe }} +{{ self::item_template_render_assoc_items(self.borrow()) | safe }} +{{ self::item_template_document_type_layout(self.borrow()) | safe }} From 39c9c506fb48af092b2cfa517ff7e09735c62475 Mon Sep 17 00:00:00 2001 From: Nicky Lim Date: Mon, 12 Jun 2023 18:55:03 +0800 Subject: [PATCH 10/13] Use `item_template` macro --- src/librustdoc/html/render/print_item.rs | 95 +++++-------------- .../html/templates/item_struct.html | 8 +- 2 files changed, 28 insertions(+), 75 deletions(-) diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 75a8dac1dd3ba..ed7fcdd545bc0 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -42,6 +42,10 @@ use crate::html::{highlight, static_files}; use askama::Template; use itertools::Itertools; +trait ItemTemplate<'a, 'cx: 'a>: askama::Template + fmt::Display { + fn item_and_mut_cx(&self) -> (&'a clean::Item, RefMut<'_, &'a mut Context<'cx>>); +} + /// Generates an Askama template struct for rendering items with common methods. /// /// Usage: @@ -126,6 +130,16 @@ macro_rules! item_template_methods { } item_template_methods!($($rest)*); }; + (render_attributes_in_code $($rest:tt)*) => { + fn render_attributes_in_code<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { + display_fn(move |f| { + let (it, cx) = self.item_and_mut_cx(); + let v = render_attributes_in_code(it, cx.tcx()); + write!(f, "{v}") + }) + } + item_template_methods!($($rest)*); + }; (render_assoc_items $($rest:tt)*) => { fn render_assoc_items<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { display_fn(move |f| { @@ -322,63 +336,6 @@ fn toggle_close(mut w: impl fmt::Write) { w.write_str("").unwrap(); } -trait ItemTemplate<'a, 'cx: 'a>: askama::Template + fmt::Display { - fn item_and_mut_cx(&self) -> (&'a clean::Item, RefMut<'_, &'a mut Context<'cx>>); -} - -fn item_template_document<'a: 'b, 'b, 'cx: 'a>( - templ: &'b impl ItemTemplate<'a, 'cx>, -) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { - display_fn(move |f| { - let (item, mut cx) = templ.item_and_mut_cx(); - let v = document(*cx, item, None, HeadingOffset::H2); - write!(f, "{v}") - }) -} - -fn item_template_document_type_layout<'a: 'b, 'b, 'cx: 'a>( - templ: &'b impl ItemTemplate<'a, 'cx>, -) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { - display_fn(move |f| { - let (item, cx) = templ.item_and_mut_cx(); - let def_id = item.item_id.expect_def_id(); - let v = document_type_layout(*cx, def_id); - write!(f, "{v}") - }) -} - -fn item_template_render_attributes_in_pre<'a: 'b, 'b, 'cx: 'a>( - templ: &'b impl ItemTemplate<'a, 'cx>, -) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { - display_fn(move |f| { - let (item, cx) = templ.item_and_mut_cx(); - let tcx = cx.tcx(); - let v = render_attributes_in_pre(item, "", tcx); - write!(f, "{v}") - }) -} - -fn item_template_render_attributes_in_code<'a: 'b, 'b, 'cx: 'a>( - templ: &'b impl ItemTemplate<'a, 'cx>, -) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { - display_fn(move |f| { - let (it, cx) = templ.item_and_mut_cx(); - let v = render_attributes_in_code(it, cx.tcx()); - write!(f, "{v}") - }) -} - -fn item_template_render_assoc_items<'a: 'b, 'b, 'cx: 'a>( - templ: &'b impl ItemTemplate<'a, 'cx>, -) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { - display_fn(move |f| { - let (item, mut cx) = templ.item_and_mut_cx(); - let def_id = item.item_id.expect_def_id(); - let v = render_assoc_items(*cx, item, def_id, AssocItemRender::All, None); - write!(f, "{v}") - }) -} - fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items: &[clean::Item]) { write!(w, "{}", document(cx, item, None, HeadingOffset::H2)); @@ -1864,14 +1821,16 @@ fn item_constant(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, c: &cle } fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Struct) { - #[derive(Template)] - #[template(path = "item_struct.html")] - struct ItemStruct<'a, 'cx> { - cx: std::cell::RefCell<&'a mut Context<'cx>>, - it: &'a clean::Item, - s: &'a clean::Struct, - should_render_fields: bool, - } + item_template!( + #[template(path = "item_struct.html")] + struct ItemStruct<'a, 'cx> { + cx: RefCell<&'a mut Context<'cx>>, + it: &'a clean::Item, + s: &'a clean::Struct, + should_render_fields: bool, + }, + methods = [render_attributes_in_code, document, render_assoc_items, document_type_layout] + ); struct Field<'a> { item: &'a clean::Item, @@ -1880,12 +1839,6 @@ fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean ty: String, } - impl<'a, 'cx: 'a> ItemTemplate<'a, 'cx> for ItemStruct<'a, 'cx> { - fn item_and_mut_cx(&self) -> (&'a clean::Item, RefMut<'_, &'a mut Context<'cx>>) { - (self.it, self.cx.borrow_mut()) - } - } - impl<'a, 'cx: 'a> ItemStruct<'a, 'cx> { fn new( cx: std::cell::RefCell<&'a mut Context<'cx>>, diff --git a/src/librustdoc/html/templates/item_struct.html b/src/librustdoc/html/templates/item_struct.html index 873bcc90687b6..22d7d1f66ceb5 100644 --- a/src/librustdoc/html/templates/item_struct.html +++ b/src/librustdoc/html/templates/item_struct.html @@ -1,8 +1,8 @@

-    {{ self::item_template_render_attributes_in_code(self.borrow()) | safe }}
+    {{ self.render_attributes_in_code() | safe }}
     {{ self.render_struct() | safe }}
 
-{{ self::item_template_document(self.borrow()) | safe }} +{{ self.document() | safe }} {% if self.should_render_fields %}

{% if self.s.ctor_kind.is_none() %} @@ -22,5 +22,5 @@

{{ self.document_field(field.item) | safe }} {% endfor %} {% endif %} -{{ self::item_template_render_assoc_items(self.borrow()) | safe }} -{{ self::item_template_document_type_layout(self.borrow()) | safe }} +{{ self.render_assoc_items() | safe }} +{{ self.document_type_layout() | safe }} From d4d96183b87c21ff4eb5f3e5c681ee4f79edd50d Mon Sep 17 00:00:00 2001 From: Nicky Lim Date: Wed, 14 Jun 2023 22:10:06 +0800 Subject: [PATCH 11/13] Combine `write!()` calls and convert to `write_str()` --- src/librustdoc/html/render/print_item.rs | 25 ++++++++++-------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index ed7fcdd545bc0..1133a0e29ced5 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -2105,7 +2105,7 @@ fn render_union<'a, 'cx: 'a>( f.write_str(" ")?; } - write!(f, "{{\n")?; + f.write_str("{{\n")?; let count_fields = fields.iter().filter(|field| matches!(*field.kind, clean::StructFieldItem(..))).count(); let toggle = should_hide_fields(count_fields); @@ -2126,7 +2126,7 @@ fn render_union<'a, 'cx: 'a>( } if it.has_stripped_entries().unwrap() { - write!(f, " /* private fields */\n")?; + f.write_str(" /* private fields */\n")?; } if toggle { toggle_close(&mut f); @@ -2164,14 +2164,9 @@ fn render_struct<'a, 'cx: 'a>( let mut buf = Buffer::html(); let where_displayed = g.map(|g| print_where_clause_and_check(&mut buf, g, cx)).unwrap_or(false); - write!(f, "{}", buf.into_inner())?; // If there wasn't a `where` clause, we add a whitespace. - if !where_displayed { - f.write_str(" {")?; - } else { - f.write_str("{")?; - } + write!(f, "{}{}{{", buf.into_inner(), if !where_displayed { " " } else { "" })?; let count_fields = fields .iter() @@ -2201,7 +2196,7 @@ fn render_struct<'a, 'cx: 'a>( } write!(f, "\n{}", tab)?; } else if it.has_stripped_entries().unwrap() { - write!(f, " /* private fields */ ")?; + f.write_str(" /* private fields */ ")?; } if toggle { toggle_close(&mut f); @@ -2209,14 +2204,14 @@ fn render_struct<'a, 'cx: 'a>( f.write_str("}")?; } Some(CtorKind::Fn) => { - write!(f, "(")?; + f.write_str("(")?; for (i, field) in fields.iter().enumerate() { if i > 0 { - write!(f, ", ")?; + f.write_str(", ")?; } match *field.kind { clean::StrippedItem(box clean::StructFieldItem(..)) => { - write!(f, "_")?; + f.write_str("_")?; } clean::StructFieldItem(ref ty) => { write!( @@ -2233,13 +2228,13 @@ fn render_struct<'a, 'cx: 'a>( _ => unreachable!(), } } - write!(f, ")")?; + f.write_str(")")?; if let Some(g) = g { write!(f, "{}", print_where_clause(g, cx, 0, Ending::NoNewline))?; } // We only want a ";" when we are displaying a tuple struct, not a variant tuple struct. if structhead { - write!(f, ";")?; + f.write_str(";")?; } } Some(CtorKind::Const) => { @@ -2247,7 +2242,7 @@ fn render_struct<'a, 'cx: 'a>( if let Some(g) = g { write!(f, "{}", print_where_clause(g, cx, 0, Ending::NoNewline))?; } - write!(f, ";")?; + f.write_str(";")?; } } Ok(()) From faacad5a3c576e1bd72c94d84357437264fe04d2 Mon Sep 17 00:00:00 2001 From: Nicky Lim Date: Wed, 14 Jun 2023 22:34:05 +0800 Subject: [PATCH 12/13] Remove extra `{` --- src/librustdoc/html/render/print_item.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 1133a0e29ced5..7a85690351d88 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -2105,7 +2105,7 @@ fn render_union<'a, 'cx: 'a>( f.write_str(" ")?; } - f.write_str("{{\n")?; + f.write_str("{\n")?; let count_fields = fields.iter().filter(|field| matches!(*field.kind, clean::StructFieldItem(..))).count(); let toggle = should_hide_fields(count_fields); From 5e3980bc174e3e3c9dc1f605afaaaf0055c07b08 Mon Sep 17 00:00:00 2001 From: Nicky Lim Date: Fri, 16 Jun 2023 00:08:16 +0800 Subject: [PATCH 13/13] Move item template structs outside of function --- src/librustdoc/html/render/print_item.rs | 238 ++++++++++++----------- 1 file changed, 120 insertions(+), 118 deletions(-) diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 7a85690351d88..112b155db3eeb 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -1331,67 +1331,68 @@ fn item_type_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &c write!(w, "{}", document_type_layout(cx, def_id)); } -fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Union) { - item_template!( - #[template(path = "item_union.html")] - struct ItemUnion<'a, 'cx> { - cx: RefCell<&'a mut Context<'cx>>, - it: &'a clean::Item, - s: &'a clean::Union, - }, - methods = [document, document_type_layout, render_attributes_in_pre, render_assoc_items] - ); +// Only to be used by the `item_union()` function +item_template!( + #[template(path = "item_union.html")] + struct ItemUnion<'a, 'cx> { + cx: RefCell<&'a mut Context<'cx>>, + it: &'a clean::Item, + s: &'a clean::Union, + }, + methods = [document, document_type_layout, render_attributes_in_pre, render_assoc_items] +); + +impl<'a, 'cx: 'a> ItemUnion<'a, 'cx> { + fn render_union<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { + display_fn(move |f| { + let cx = self.cx.borrow_mut(); + let v = render_union(self.it, Some(&self.s.generics), &self.s.fields, *cx); + write!(f, "{v}") + }) + } - impl<'a, 'cx: 'a> ItemUnion<'a, 'cx> { - fn render_union<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { - display_fn(move |f| { - let cx = self.cx.borrow_mut(); - let v = render_union(self.it, Some(&self.s.generics), &self.s.fields, *cx); - write!(f, "{v}") - }) - } + fn document_field<'b>( + &'b self, + field: &'a clean::Item, + ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { + display_fn(move |f| { + let mut cx = self.cx.borrow_mut(); + let v = document(*cx, field, Some(self.it), HeadingOffset::H3); + write!(f, "{v}") + }) + } - fn document_field<'b>( - &'b self, - field: &'a clean::Item, - ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { - display_fn(move |f| { - let mut cx = self.cx.borrow_mut(); - let v = document(*cx, field, Some(self.it), HeadingOffset::H3); - write!(f, "{v}") - }) - } + fn stability_field(&self, field: &clean::Item) -> Option { + let cx = self.cx.borrow(); + field.stability_class(cx.tcx()) + } - fn stability_field(&self, field: &clean::Item) -> Option { + fn print_ty<'b>( + &'b self, + ty: &'a clean::Type, + ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { + display_fn(move |f| { let cx = self.cx.borrow(); - field.stability_class(cx.tcx()) - } + let v = ty.print(*cx); + write!(f, "{v}") + }) + } - fn print_ty<'b>( - &'b self, - ty: &'a clean::Type, - ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { - display_fn(move |f| { - let cx = self.cx.borrow(); - let v = ty.print(*cx); - write!(f, "{v}") + fn fields_iter( + &self, + ) -> std::iter::Peekable> { + self.s + .fields + .iter() + .filter_map(|f| match *f.kind { + clean::StructFieldItem(ref ty) => Some((f, ty)), + _ => None, }) - } - - fn fields_iter( - &self, - ) -> std::iter::Peekable> { - self.s - .fields - .iter() - .filter_map(|f| match *f.kind { - clean::StructFieldItem(ref ty) => Some((f, ty)), - _ => None, - }) - .peekable() - } + .peekable() } +} +fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Union) { ItemUnion { cx: RefCell::new(cx), it, s }.render_into(w).unwrap(); } @@ -1820,77 +1821,78 @@ fn item_constant(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, c: &cle write!(w, "{}", document(cx, it, None, HeadingOffset::H2)) } -fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Struct) { - item_template!( - #[template(path = "item_struct.html")] - struct ItemStruct<'a, 'cx> { - cx: RefCell<&'a mut Context<'cx>>, - it: &'a clean::Item, - s: &'a clean::Struct, - should_render_fields: bool, - }, - methods = [render_attributes_in_code, document, render_assoc_items, document_type_layout] - ); - - struct Field<'a> { - item: &'a clean::Item, - name: String, - id: String, - ty: String, +// Only to be used by the `item_struct()` function +item_template!( + #[template(path = "item_struct.html")] + struct ItemStruct<'a, 'cx> { + cx: RefCell<&'a mut Context<'cx>>, + it: &'a clean::Item, + s: &'a clean::Struct, + should_render_fields: bool, + }, + methods = [render_attributes_in_code, document, render_assoc_items, document_type_layout] +); + +impl<'a, 'cx: 'a> ItemStruct<'a, 'cx> { + fn new( + cx: std::cell::RefCell<&'a mut Context<'cx>>, + it: &'a clean::Item, + s: &'a clean::Struct, + ) -> Self { + let should_render_fields = matches!(s.ctor_kind, None | Some(CtorKind::Fn)) + && struct_field_items(s).peekable().peek().is_some(); + Self { cx, it, s, should_render_fields } } - impl<'a, 'cx: 'a> ItemStruct<'a, 'cx> { - fn new( - cx: std::cell::RefCell<&'a mut Context<'cx>>, - it: &'a clean::Item, - s: &'a clean::Struct, - ) -> Self { - let should_render_fields = matches!(s.ctor_kind, None | Some(CtorKind::Fn)) - && struct_field_items(s).peekable().peek().is_some(); - Self { cx, it, s, should_render_fields } - } - - fn render_struct<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { - display_fn(move |f| { - let cx = self.cx.borrow(); - let v = render_struct( - self.it, - Some(&self.s.generics), - self.s.ctor_kind, - &self.s.fields, - "", - true, - *cx, - ); - write!(f, "{v}") - }) - } + fn render_struct<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { + display_fn(move |f| { + let cx = self.cx.borrow(); + let v = render_struct( + self.it, + Some(&self.s.generics), + self.s.ctor_kind, + &self.s.fields, + "", + true, + *cx, + ); + write!(f, "{v}") + }) + } - fn struct_field_items_iter<'b>( - &'b self, - ) -> impl Iterator> + Captures<'a> + 'b + Captures<'cx> { - struct_field_items(self.s).enumerate().map(|(index, (item, ty))| { - let mut cx = self.cx.borrow_mut(); - let name = - item.name.map_or_else(|| index.to_string(), |sym| sym.as_str().to_string()); - let id = cx.derive_id(format!("{}.{}", ItemType::StructField, name)); - let ty = ty.print(*cx).to_string(); - Field { item, name, id, ty } - }) - } + fn struct_field_items_iter<'b>( + &'b self, + ) -> impl Iterator> + Captures<'a> + 'b + Captures<'cx> { + struct_field_items(self.s).enumerate().map(|(index, (item, ty))| { + let mut cx = self.cx.borrow_mut(); + let name = item.name.map_or_else(|| index.to_string(), |sym| sym.as_str().to_string()); + let id = cx.derive_id(format!("{}.{}", ItemType::StructField, name)); + let ty = ty.print(*cx).to_string(); + ItemStructField { item, name, id, ty } + }) + } - fn document_field<'b>( - &'b self, - field: &'b clean::Item, - ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { - display_fn(move |f| { - let mut cx = self.cx.borrow_mut(); - let v = document(*cx, field, Some(self.it), HeadingOffset::H3); - write!(f, "{v}") - }) - } + fn document_field<'b>( + &'b self, + field: &'b clean::Item, + ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { + display_fn(move |f| { + let mut cx = self.cx.borrow_mut(); + let v = document(*cx, field, Some(self.it), HeadingOffset::H3); + write!(f, "{v}") + }) } +} + +// Only to be used by the `ItemStruct` struct +struct ItemStructField<'a> { + item: &'a clean::Item, + name: String, + id: String, + ty: String, +} +fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Struct) { ItemStruct::new(std::cell::RefCell::new(cx), it, s).render_into(w).unwrap(); }