Skip to content

Commit

Permalink
Unrolled build for rust-lang#136784
Browse files Browse the repository at this point in the history
Rollup merge of rust-lang#136784 - yotamofek:pr/rustdoc-remove-buffer-take2, r=GuillaumeGomez

Nuke `Buffer` abstraction from `librustdoc`, take 2 💣

In rust-lang#136656 I found out that the for_html field in the Buffer struct was never read, and pondered if Buffer had any utility at all. `@GuillaumeGomez` said he agrees that it can be just removed. So this PR is me removing it. So, r? `@aDotInTheVoid` , maybe?

Supersedes rust-lang#136748
  • Loading branch information
rust-timer authored Feb 12, 2025
2 parents ced8e65 + d99d8c2 commit 728127b
Show file tree
Hide file tree
Showing 13 changed files with 710 additions and 648 deletions.
123 changes: 9 additions & 114 deletions src/librustdoc/html/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,113 +37,8 @@ use crate::html::render::Context;
use crate::joined::Joined as _;
use crate::passes::collect_intra_doc_links::UrlFragment;

pub(crate) trait Print {
fn print(self, buffer: &mut Buffer);
}

impl<F> Print for F
where
F: FnOnce(&mut Buffer),
{
fn print(self, buffer: &mut Buffer) {
(self)(buffer)
}
}

impl Print for String {
fn print(self, buffer: &mut Buffer) {
buffer.write_str(&self);
}
}

impl Print for &'_ str {
fn print(self, buffer: &mut Buffer) {
buffer.write_str(self);
}
}

#[derive(Debug, Clone)]
pub(crate) struct Buffer {
for_html: bool,
buffer: String,
}

impl core::fmt::Write for Buffer {
#[inline]
fn write_str(&mut self, s: &str) -> fmt::Result {
self.buffer.write_str(s)
}

#[inline]
fn write_char(&mut self, c: char) -> fmt::Result {
self.buffer.write_char(c)
}

#[inline]
fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> fmt::Result {
self.buffer.write_fmt(args)
}
}

impl Buffer {
pub(crate) fn empty_from(v: &Buffer) -> Buffer {
Buffer { for_html: v.for_html, buffer: String::new() }
}

pub(crate) fn html() -> Buffer {
Buffer { for_html: true, buffer: String::new() }
}

pub(crate) fn new() -> Buffer {
Buffer { for_html: false, buffer: String::new() }
}

pub(crate) fn is_empty(&self) -> bool {
self.buffer.is_empty()
}

pub(crate) fn into_inner(self) -> String {
self.buffer
}

pub(crate) fn push(&mut self, c: char) {
self.buffer.push(c);
}

pub(crate) fn push_str(&mut self, s: &str) {
self.buffer.push_str(s);
}

pub(crate) fn push_buffer(&mut self, other: Buffer) {
self.buffer.push_str(&other.buffer);
}

// Intended for consumption by write! and writeln! (std::fmt) but without
// the fmt::Result return type imposed by fmt::Write (and avoiding the trait
// import).
pub(crate) fn write_str(&mut self, s: &str) {
self.buffer.push_str(s);
}

// Intended for consumption by write! and writeln! (std::fmt) but without
// the fmt::Result return type imposed by fmt::Write (and avoiding the trait
// import).
pub(crate) fn write_fmt(&mut self, v: fmt::Arguments<'_>) {
self.buffer.write_fmt(v).unwrap();
}

pub(crate) fn to_display<T: Print>(mut self, t: T) -> String {
t.print(&mut self);
self.into_inner()
}

pub(crate) fn reserve(&mut self, additional: usize) {
self.buffer.reserve(additional)
}

pub(crate) fn len(&self) -> usize {
self.buffer.len()
}
pub(crate) fn write_str(s: &mut String, f: fmt::Arguments<'_>) {
s.write_fmt(f).unwrap();
}

pub(crate) fn print_generic_bounds<'a, 'tcx: 'a>(
Expand Down Expand Up @@ -772,27 +667,27 @@ pub(crate) fn link_tooltip(did: DefId, fragment: &Option<UrlFragment>, cx: &Cont
else {
return String::new();
};
let mut buf = Buffer::new();
let mut buf = String::new();
let fqp = if *shortty == ItemType::Primitive {
// primitives are documented in a crate, but not actually part of it
&fqp[fqp.len() - 1..]
} else {
fqp
};
if let &Some(UrlFragment::Item(id)) = fragment {
write!(buf, "{} ", cx.tcx().def_descr(id));
write_str(&mut buf, format_args!("{} ", cx.tcx().def_descr(id)));
for component in fqp {
write!(buf, "{component}::");
write_str(&mut buf, format_args!("{component}::"));
}
write!(buf, "{}", cx.tcx().item_name(id));
write_str(&mut buf, format_args!("{}", cx.tcx().item_name(id)));
} else if !fqp.is_empty() {
let mut fqp_it = fqp.iter();
write!(buf, "{shortty} {}", fqp_it.next().unwrap());
write_str(&mut buf, format_args!("{shortty} {}", fqp_it.next().unwrap()));
for component in fqp_it {
write!(buf, "::{component}");
write_str(&mut buf, format_args!("::{component}"));
}
}
buf.into_inner()
buf
}

/// Used to render a [`clean::Path`].
Expand Down
80 changes: 44 additions & 36 deletions src/librustdoc/html/highlight.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use rustc_span::edition::Edition;
use rustc_span::symbol::Symbol;
use rustc_span::{BytePos, DUMMY_SP, Span};

use super::format::{self, Buffer};
use super::format::{self, write_str};
use crate::clean::PrimitiveType;
use crate::html::escape::EscapeBodyText;
use crate::html::render::{Context, LinkFromSrc};
Expand Down Expand Up @@ -48,7 +48,7 @@ pub(crate) enum Tooltip {
/// Highlights `src` as an inline example, returning the HTML output.
pub(crate) fn render_example_with_highlighting(
src: &str,
out: &mut Buffer,
out: &mut String,
tooltip: Tooltip,
playground_button: Option<&str>,
extra_classes: &[String],
Expand All @@ -59,61 +59,69 @@ pub(crate) fn render_example_with_highlighting(
}

fn write_header(
out: &mut Buffer,
out: &mut String,
class: &str,
extra_content: Option<Buffer>,
extra_content: Option<&str>,
tooltip: Tooltip,
extra_classes: &[String],
) {
write!(
write_str(
out,
"<div class=\"example-wrap{}\">",
match tooltip {
Tooltip::Ignore => " ignore",
Tooltip::CompileFail => " compile_fail",
Tooltip::ShouldPanic => " should_panic",
Tooltip::Edition(_) => " edition",
Tooltip::None => "",
},
format_args!(
"<div class=\"example-wrap{}\">",
match tooltip {
Tooltip::Ignore => " ignore",
Tooltip::CompileFail => " compile_fail",
Tooltip::ShouldPanic => " should_panic",
Tooltip::Edition(_) => " edition",
Tooltip::None => "",
}
),
);

if tooltip != Tooltip::None {
let edition_code;
write!(
write_str(
out,
"<a href=\"#\" class=\"tooltip\" title=\"{}\">ⓘ</a>",
match tooltip {
Tooltip::Ignore => "This example is not tested",
Tooltip::CompileFail => "This example deliberately fails to compile",
Tooltip::ShouldPanic => "This example panics",
Tooltip::Edition(edition) => {
edition_code = format!("This example runs with edition {edition}");
&edition_code
format_args!(
"<a href=\"#\" class=\"tooltip\" title=\"{}\">ⓘ</a>",
match tooltip {
Tooltip::Ignore => "This example is not tested",
Tooltip::CompileFail => "This example deliberately fails to compile",
Tooltip::ShouldPanic => "This example panics",
Tooltip::Edition(edition) => {
edition_code = format!("This example runs with edition {edition}");
&edition_code
}
Tooltip::None => unreachable!(),
}
Tooltip::None => unreachable!(),
},
),
);
}

if let Some(extra) = extra_content {
out.push_buffer(extra);
out.push_str(&extra);
}
if class.is_empty() {
write!(
write_str(
out,
"<pre class=\"rust{}{}\">",
if extra_classes.is_empty() { "" } else { " " },
extra_classes.join(" "),
format_args!(
"<pre class=\"rust{}{}\">",
if extra_classes.is_empty() { "" } else { " " },
extra_classes.join(" ")
),
);
} else {
write!(
write_str(
out,
"<pre class=\"rust {class}{}{}\">",
if extra_classes.is_empty() { "" } else { " " },
extra_classes.join(" "),
format_args!(
"<pre class=\"rust {class}{}{}\">",
if extra_classes.is_empty() { "" } else { " " },
extra_classes.join(" ")
),
);
}
write!(out, "<code>");
write_str(out, format_args!("<code>"));
}

/// Check if two `Class` can be merged together. In the following rules, "unclassified" means `None`
Expand Down Expand Up @@ -398,8 +406,8 @@ pub(super) fn write_code(
});
}

fn write_footer(out: &mut Buffer, playground_button: Option<&str>) {
writeln!(out, "</code></pre>{}</div>", playground_button.unwrap_or_default());
fn write_footer(out: &mut String, playground_button: Option<&str>) {
write_str(out, format_args_nl!("</code></pre>{}</div>", playground_button.unwrap_or_default()));
}

/// How a span of text is classified. Mostly corresponds to token kinds.
Expand Down
21 changes: 10 additions & 11 deletions src/librustdoc/html/highlight/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use rustc_data_structures::fx::FxIndexMap;
use rustc_span::create_default_session_globals_then;

use super::{DecorationInfo, write_code};
use crate::html::format::Buffer;

const STYLE: &str = r#"
<style>
Expand All @@ -22,9 +21,9 @@ fn test_html_highlighting() {
create_default_session_globals_then(|| {
let src = include_str!("fixtures/sample.rs");
let html = {
let mut out = Buffer::new();
let mut out = String::new();
write_code(&mut out, src, None, None, None);
format!("{STYLE}<pre><code>{}</code></pre>\n", out.into_inner())
format!("{STYLE}<pre><code>{out}</code></pre>\n")
};
expect_file!["fixtures/sample.html"].assert_eq(&html);
});
Expand All @@ -36,9 +35,9 @@ fn test_dos_backline() {
let src = "pub fn foo() {\r\n\
println!(\"foo\");\r\n\
}\r\n";
let mut html = Buffer::new();
let mut html = String::new();
write_code(&mut html, src, None, None, None);
expect_file!["fixtures/dos_line.html"].assert_eq(&html.into_inner());
expect_file!["fixtures/dos_line.html"].assert_eq(&html);
});
}

Expand All @@ -50,19 +49,19 @@ use self::whatever;
let x = super::b::foo;
let y = Self::whatever;";

let mut html = Buffer::new();
let mut html = String::new();
write_code(&mut html, src, None, None, None);
expect_file!["fixtures/highlight.html"].assert_eq(&html.into_inner());
expect_file!["fixtures/highlight.html"].assert_eq(&html);
});
}

#[test]
fn test_union_highlighting() {
create_default_session_globals_then(|| {
let src = include_str!("fixtures/union.rs");
let mut html = Buffer::new();
let mut html = String::new();
write_code(&mut html, src, None, None, None);
expect_file!["fixtures/union.html"].assert_eq(&html.into_inner());
expect_file!["fixtures/union.html"].assert_eq(&html);
});
}

Expand All @@ -77,8 +76,8 @@ let a = 4;";
decorations.insert("example", vec![(0, 10), (11, 21)]);
decorations.insert("example2", vec![(22, 32)]);

let mut html = Buffer::new();
let mut html = String::new();
write_code(&mut html, src, None, Some(&DecorationInfo(decorations)), None);
expect_file!["fixtures/decorations.html"].assert_eq(&html.into_inner());
expect_file!["fixtures/decorations.html"].assert_eq(&html);
});
}
25 changes: 21 additions & 4 deletions src/librustdoc/html/layout.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use std::fmt::{self, Display};
use std::path::PathBuf;

use rinja::Template;
use rustc_data_structures::fx::FxIndexMap;

use super::static_files::{STATIC_FILES, StaticFiles};
use crate::externalfiles::ExternalHtml;
use crate::html::format::{Buffer, Print};
use crate::html::render::{StylePath, ensure_trailing_slash};

#[derive(Clone)]
Expand Down Expand Up @@ -71,7 +71,24 @@ struct PageLayout<'a> {

pub(crate) use crate::html::render::sidebar::filters;

pub(crate) fn render<T: Print, S: Print>(
/// Implements [`Display`] for a function that accepts a mutable reference to a [`String`], and (optionally) writes to it.
///
/// The wrapped function will receive an empty string, and can modify it,
/// and the `Display` implementation will write the contents of the string after the function has finished.
pub(crate) struct BufDisplay<F>(pub F);

impl<F> Display for BufDisplay<F>
where
F: Fn(&mut String),
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut buf = String::new();
self.0(&mut buf);
f.write_str(&buf)
}
}

pub(crate) fn render<T: Display, S: Display>(
layout: &Layout,
page: &Page<'_>,
sidebar: S,
Expand All @@ -98,8 +115,8 @@ pub(crate) fn render<T: Print, S: Print>(
let mut themes: Vec<String> = style_files.iter().map(|s| s.basename().unwrap()).collect();
themes.sort();

let content = Buffer::html().to_display(t); // Note: This must happen before making the sidebar.
let sidebar = Buffer::html().to_display(sidebar);
let content = t.to_string(); // Note: This must happen before making the sidebar.
let sidebar = sidebar.to_string();
PageLayout {
static_root_path,
page,
Expand Down
Loading

0 comments on commit 728127b

Please sign in to comment.