From c748551f7f006638d323cde079aaba30a49b185b Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 19 Jun 2022 16:36:58 +0200 Subject: [PATCH 1/2] Fix invalid add of whitespace when there is where clause --- src/librustdoc/html/format.rs | 4 ++ src/librustdoc/html/render/print_item.rs | 55 ++++++++++++++++++------ 2 files changed, 45 insertions(+), 14 deletions(-) diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 5584ecd287a53..0982c4b3acec8 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -146,6 +146,10 @@ impl Buffer { pub(crate) fn reserve(&mut self, additional: usize) { self.buffer.reserve(additional) } + + pub(crate) fn len(&self) -> usize { + self.buffer.len() + } } fn comma_sep( diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index fe00f952e043c..3525007baf369 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -62,6 +62,17 @@ struct ItemVars<'a> { src_href: Option<&'a str>, } +/// Calls `print_where_clause` and returns `true` if a `where` clause was generated. +fn print_where_clause_and_check<'a, 'tcx: 'a>( + buffer: &mut Buffer, + gens: &'a clean::Generics, + cx: &'a Context<'tcx>, +) -> bool { + let len_before = buffer.len(); + write!(buffer, "{}", print_where_clause(gens, cx, 0, true)); + len_before != buffer.len() +} + pub(super) fn print_item( cx: &mut Context<'_>, item: &clean::Item, @@ -1152,17 +1163,21 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean:: render_attributes_in_pre(w, it, ""); write!( w, - "{}enum {}{}{}", + "{}enum {}{}", it.visibility.print_with_space(it.item_id, cx), it.name.unwrap(), e.generics.print(cx), - print_where_clause(&e.generics, cx, 0, true), ); + if !print_where_clause_and_check(w, &e.generics, cx) { + // If there wasn't a `where` clause, we add a whitespace. + w.write_str(" "); + } + let variants_stripped = e.has_stripped_entries(); if count_variants == 0 && !variants_stripped { - w.write_str(" {}"); + w.write_str("{}"); } else { - w.write_str(" {\n"); + w.write_str("{\n"); let toggle = should_hide_fields(count_variants); if toggle { toggle_open(w, format_args!("{} variants", count_variants)); @@ -1643,13 +1658,21 @@ fn render_union( tab: &str, cx: &Context<'_>, ) { - write!(w, "{}union {}", it.visibility.print_with_space(it.item_id, cx), it.name.unwrap()); - if let Some(g) = g { - write!(w, "{}", g.print(cx)); - write!(w, "{}", print_where_clause(g, cx, 0, true)); + write!(w, "{}union {}", it.visibility.print_with_space(it.item_id, cx), it.name.unwrap(),); + + let where_displayed = g + .map(|g| { + write!(w, "{}", g.print(cx)); + print_where_clause_and_check(w, g, cx) + }) + .unwrap_or(false); + + // If there wasn't a `where` clause, we add a whitespace. + if !where_displayed { + w.write_str(" "); } - write!(w, " {{\n{}", tab); + write!(w, "{{\n{}", tab); let count_fields = fields.iter().filter(|f| matches!(*f.kind, clean::StructFieldItem(..))).count(); let toggle = should_hide_fields(count_fields); @@ -1701,10 +1724,14 @@ fn render_struct( } match ty { CtorKind::Fictive => { - if let Some(g) = g { - write!(w, "{}", print_where_clause(g, cx, 0, true),) + let where_diplayed = g.map(|g| print_where_clause_and_check(w, g, cx)).unwrap_or(false); + + // If there wasn't a `where` clause, we add a whitespace. + if !where_diplayed { + w.write_str(" {"); + } else { + w.write_str("{"); } - w.write_str(" {"); let count_fields = fields.iter().filter(|f| matches!(*f.kind, clean::StructFieldItem(..))).count(); let has_visible_fields = count_fields > 0; @@ -1759,7 +1786,7 @@ fn render_struct( } w.write_str(")"); if let Some(g) = g { - write!(w, "{}", print_where_clause(g, cx, 0, false),) + write!(w, "{}", print_where_clause(g, cx, 0, false)); } // We only want a ";" when we are displaying a tuple struct, not a variant tuple struct. if structhead { @@ -1769,7 +1796,7 @@ fn render_struct( CtorKind::Const => { // Needed for PhantomData. if let Some(g) = g { - write!(w, "{}", print_where_clause(g, cx, 0, false),) + write!(w, "{}", print_where_clause(g, cx, 0, false)); } w.write_str(";"); } From c8a5b671a0395706621430a57c258b85a30bad71 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 19 Jun 2022 16:38:10 +0200 Subject: [PATCH 2/2] Add test for invalid whitespace display after where clause --- .../whitespace-after-where-clause.enum.html | 4 + .../whitespace-after-where-clause.enum2.html | 4 + .../rustdoc/whitespace-after-where-clause.rs | 77 +++++++++++++++++++ .../whitespace-after-where-clause.struct.html | 4 + ...whitespace-after-where-clause.struct2.html | 4 + .../whitespace-after-where-clause.trait.html | 6 ++ .../whitespace-after-where-clause.trait2.html | 6 ++ .../whitespace-after-where-clause.union.html | 3 + .../whitespace-after-where-clause.union2.html | 3 + 9 files changed, 111 insertions(+) create mode 100644 src/test/rustdoc/whitespace-after-where-clause.enum.html create mode 100644 src/test/rustdoc/whitespace-after-where-clause.enum2.html create mode 100644 src/test/rustdoc/whitespace-after-where-clause.rs create mode 100644 src/test/rustdoc/whitespace-after-where-clause.struct.html create mode 100644 src/test/rustdoc/whitespace-after-where-clause.struct2.html create mode 100644 src/test/rustdoc/whitespace-after-where-clause.trait.html create mode 100644 src/test/rustdoc/whitespace-after-where-clause.trait2.html create mode 100644 src/test/rustdoc/whitespace-after-where-clause.union.html create mode 100644 src/test/rustdoc/whitespace-after-where-clause.union2.html diff --git a/src/test/rustdoc/whitespace-after-where-clause.enum.html b/src/test/rustdoc/whitespace-after-where-clause.enum.html new file mode 100644 index 0000000000000..9e5bf45ae7d2f --- /dev/null +++ b/src/test/rustdoc/whitespace-after-where-clause.enum.html @@ -0,0 +1,4 @@ +
pub enum Cow<'a, B: ?Sized + 'a> where
    B: ToOwned<dyn Clone>, 
{ + Borrowed(&'a B), + Whatever(u32), +}
diff --git a/src/test/rustdoc/whitespace-after-where-clause.enum2.html b/src/test/rustdoc/whitespace-after-where-clause.enum2.html new file mode 100644 index 0000000000000..6bc47beaed125 --- /dev/null +++ b/src/test/rustdoc/whitespace-after-where-clause.enum2.html @@ -0,0 +1,4 @@ +
pub enum Cow2<'a, B: ?Sized + ToOwned<dyn Clone> + 'a> {
+    Borrowed(&'a B),
+    Whatever(u32),
+}
diff --git a/src/test/rustdoc/whitespace-after-where-clause.rs b/src/test/rustdoc/whitespace-after-where-clause.rs new file mode 100644 index 0000000000000..c36386a2aa2b5 --- /dev/null +++ b/src/test/rustdoc/whitespace-after-where-clause.rs @@ -0,0 +1,77 @@ +// This test ensures there is no whitespace before the first brace of +// trait, enum, struct and union items when they have a where clause. + +#![crate_name = "foo"] + +// @has 'foo/trait.ToOwned.html' +// @snapshot trait - '//*[@class="docblock item-decl"]' +pub trait ToOwned +where T: Clone +{ + type Owned; + fn to_owned(&self) -> Self::Owned; + fn whatever(&self) -> T; +} + +// @has 'foo/trait.ToOwned2.html' +// @snapshot trait2 - '//*[@class="docblock item-decl"]' +// There should be a whitespace before `{` in this case! +pub trait ToOwned2 { + type Owned; + fn to_owned(&self) -> Self::Owned; + fn whatever(&self) -> T; +} + +// @has 'foo/enum.Cow.html' +// @snapshot enum - '//*[@class="docblock item-decl"]' +pub enum Cow<'a, B: ?Sized + 'a> +where + B: ToOwned, +{ + Borrowed(&'a B), + Whatever(u32), +} + +// @has 'foo/enum.Cow2.html' +// @snapshot enum2 - '//*[@class="docblock item-decl"]' +// There should be a whitespace before `{` in this case! +pub enum Cow2<'a, B: ?Sized + ToOwned + 'a> { + Borrowed(&'a B), + Whatever(u32), +} + +// @has 'foo/struct.Struct.html' +// @snapshot struct - '//*[@class="docblock item-decl"]' +pub struct Struct<'a, B: ?Sized + 'a> +where + B: ToOwned, +{ + pub a: &'a B, + pub b: u32, +} + +// @has 'foo/struct.Struct2.html' +// @snapshot struct2 - '//*[@class="docblock item-decl"]' +// There should be a whitespace before `{` in this case! +pub struct Struct2<'a, B: ?Sized + ToOwned + 'a> { + pub a: &'a B, + pub b: u32, +} + +// @has 'foo/union.Union.html' +// @snapshot union - '//*[@class="docblock item-decl"]' +pub union Union<'a, B: ?Sized + 'a> +where + B: ToOwned, +{ + a: &'a B, + b: u32, +} + +// @has 'foo/union.Union2.html' +// @snapshot union2 - '//*[@class="docblock item-decl"]' +// There should be a whitespace before `{` in this case! +pub union Union2<'a, B: ?Sized + ToOwned + 'a> { + a: &'a B, + b: u32, +} diff --git a/src/test/rustdoc/whitespace-after-where-clause.struct.html b/src/test/rustdoc/whitespace-after-where-clause.struct.html new file mode 100644 index 0000000000000..236cc3b30d088 --- /dev/null +++ b/src/test/rustdoc/whitespace-after-where-clause.struct.html @@ -0,0 +1,4 @@ +
pub struct Struct<'a, B: ?Sized + 'a> where
    B: ToOwned<dyn Clone>, 
{ + pub a: &'a B, + pub b: u32, +}
diff --git a/src/test/rustdoc/whitespace-after-where-clause.struct2.html b/src/test/rustdoc/whitespace-after-where-clause.struct2.html new file mode 100644 index 0000000000000..47f5c6ba9c846 --- /dev/null +++ b/src/test/rustdoc/whitespace-after-where-clause.struct2.html @@ -0,0 +1,4 @@ +
pub struct Struct2<'a, B: ?Sized + ToOwned<dyn Clone> + 'a> {
+    pub a: &'a B,
+    pub b: u32,
+}
diff --git a/src/test/rustdoc/whitespace-after-where-clause.trait.html b/src/test/rustdoc/whitespace-after-where-clause.trait.html new file mode 100644 index 0000000000000..98f03b837b528 --- /dev/null +++ b/src/test/rustdoc/whitespace-after-where-clause.trait.html @@ -0,0 +1,6 @@ +
pub trait ToOwned<T> where
    T: Clone
{ + type Owned; + + fn to_owned(&self) -> Self::Owned; + fn whatever(&self) -> T; +}
diff --git a/src/test/rustdoc/whitespace-after-where-clause.trait2.html b/src/test/rustdoc/whitespace-after-where-clause.trait2.html new file mode 100644 index 0000000000000..35052869e762d --- /dev/null +++ b/src/test/rustdoc/whitespace-after-where-clause.trait2.html @@ -0,0 +1,6 @@ +
pub trait ToOwned2<T: Clone> {
+    type Owned;
+
+    fn to_owned(&self) -> Self::Owned;
+    fn whatever(&self) -> T;
+}
diff --git a/src/test/rustdoc/whitespace-after-where-clause.union.html b/src/test/rustdoc/whitespace-after-where-clause.union.html new file mode 100644 index 0000000000000..97e1bbcf339f8 --- /dev/null +++ b/src/test/rustdoc/whitespace-after-where-clause.union.html @@ -0,0 +1,3 @@ +
pub union Union<'a, B: ?Sized + 'a> where
    B: ToOwned<dyn Clone>, 
{ + /* private fields */ +}
diff --git a/src/test/rustdoc/whitespace-after-where-clause.union2.html b/src/test/rustdoc/whitespace-after-where-clause.union2.html new file mode 100644 index 0000000000000..6c752a8b4c5ea --- /dev/null +++ b/src/test/rustdoc/whitespace-after-where-clause.union2.html @@ -0,0 +1,3 @@ +
pub union Union2<'a, B: ?Sized + ToOwned<dyn Clone> + 'a> {
+    /* private fields */
+}