diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs
index 0e06361024b9f..fe2b2fc603120 100644
--- a/src/librustdoc/html/highlight.rs
+++ b/src/librustdoc/html/highlight.rs
@@ -8,6 +8,7 @@
use std::borrow::Cow;
use std::collections::VecDeque;
use std::fmt::{self, Display, Write};
+use std::iter;
use rustc_data_structures::fx::FxIndexMap;
use rustc_lexer::{Cursor, FrontmatterAllowed, LiteralKind, TokenKind};
@@ -15,8 +16,9 @@ use rustc_span::edition::Edition;
use rustc_span::symbol::Symbol;
use rustc_span::{BytePos, DUMMY_SP, Span};
-use super::format::{self, write_str};
+use super::format;
use crate::clean::PrimitiveType;
+use crate::display::Joined as _;
use crate::html::escape::EscapeBodyText;
use crate::html::macro_expansion::ExpandedCode;
use crate::html::render::{Context, LinkFromSrc};
@@ -45,92 +47,72 @@ pub(crate) enum Tooltip {
CompileFail,
ShouldPanic,
Edition(Edition),
- None,
}
/// Highlights `src` as an inline example, returning the HTML output.
pub(crate) fn render_example_with_highlighting(
src: &str,
- out: &mut String,
- tooltip: Tooltip,
+ tooltip: Option<&Tooltip>,
playground_button: Option<&str>,
extra_classes: &[String],
-) {
- write_header(out, "rust-example-rendered", None, tooltip, extra_classes);
- write_code(out, src, None, None, None);
- write_footer(out, playground_button);
+) -> impl Display {
+ fmt::from_fn(move |f| {
+ write_header("rust-example-rendered", tooltip, extra_classes).fmt(f)?;
+ write_code(f, src, None, None, None);
+ write_footer(playground_button).fmt(f)
+ })
}
-fn write_header(
- out: &mut String,
- class: &str,
- extra_content: Option<&str>,
- tooltip: Tooltip,
- extra_classes: &[String],
-) {
- write_str(
- out,
- format_args!(
+fn write_header(class: &str, tooltip: Option<&Tooltip>, extra_classes: &[String]) -> impl Display {
+ fmt::from_fn(move |f| {
+ write!(
+ f,
"
",
- match tooltip {
- Tooltip::IgnoreAll | Tooltip::IgnoreSome(_) => " ignore",
- Tooltip::CompileFail => " compile_fail",
- Tooltip::ShouldPanic => " should_panic",
- Tooltip::Edition(_) => " edition",
- Tooltip::None => "",
- }
- ),
- );
-
- if tooltip != Tooltip::None {
- let tooltip = fmt::from_fn(|f| match &tooltip {
- Tooltip::IgnoreAll => f.write_str("This example is not tested"),
- Tooltip::IgnoreSome(platforms) => {
- f.write_str("This example is not tested on ")?;
- match &platforms[..] {
- [] => unreachable!(),
- [platform] => f.write_str(platform)?,
- [first, second] => write!(f, "{first} or {second}")?,
- [platforms @ .., last] => {
- for platform in platforms {
- write!(f, "{platform}, ")?;
+ tooltip
+ .map(|tooltip| match tooltip {
+ Tooltip::IgnoreAll | Tooltip::IgnoreSome(_) => " ignore",
+ Tooltip::CompileFail => " compile_fail",
+ Tooltip::ShouldPanic => " should_panic",
+ Tooltip::Edition(_) => " edition",
+ })
+ .unwrap_or_default()
+ )?;
+
+ if let Some(tooltip) = tooltip {
+ let tooltip = fmt::from_fn(|f| match tooltip {
+ Tooltip::IgnoreAll => f.write_str("This example is not tested"),
+ Tooltip::IgnoreSome(platforms) => {
+ f.write_str("This example is not tested on ")?;
+ match &platforms[..] {
+ [] => unreachable!(),
+ [platform] => f.write_str(platform)?,
+ [first, second] => write!(f, "{first} or {second}")?,
+ [platforms @ .., last] => {
+ for platform in platforms {
+ write!(f, "{platform}, ")?;
+ }
+ write!(f, "or {last}")?;
}
- write!(f, "or {last}")?;
}
+ Ok(())
}
- Ok(())
- }
- Tooltip::CompileFail => f.write_str("This example deliberately fails to compile"),
- Tooltip::ShouldPanic => f.write_str("This example panics"),
- Tooltip::Edition(edition) => write!(f, "This example runs with edition {edition}"),
- Tooltip::None => unreachable!(),
+ Tooltip::CompileFail => f.write_str("This example deliberately fails to compile"),
+ Tooltip::ShouldPanic => f.write_str("This example panics"),
+ Tooltip::Edition(edition) => write!(f, "This example runs with edition {edition}"),
+ });
+
+ write!(f, "
ⓘ")?;
+ }
+
+ let classes = fmt::from_fn(|f| {
+ iter::once("rust")
+ .chain(Some(class).filter(|class| !class.is_empty()))
+ .chain(extra_classes.iter().map(String::as_str))
+ .joined(" ", f)
});
- write_str(out, format_args!("
ⓘ"));
- }
- if let Some(extra) = extra_content {
- out.push_str(extra);
- }
- if class.is_empty() {
- write_str(
- out,
- format_args!(
- "
",
- if extra_classes.is_empty() { "" } else { " " },
- extra_classes.join(" ")
- ),
- );
- } else {
- write_str(
- out,
- format_args!(
- "",
- if extra_classes.is_empty() { "" } else { " " },
- extra_classes.join(" ")
- ),
- );
- }
- write_str(out, format_args!(""));
+ write!(f, "")
+ })
}
/// Check if two `Class` can be merged together. In the following rules, "unclassified" means `None`
@@ -577,8 +559,8 @@ pub(super) fn write_code(
});
}
-fn write_footer(out: &mut String, playground_button: Option<&str>) {
- write_str(out, format_args!("
{}
", playground_button.unwrap_or_default()));
+fn write_footer(playground_button: Option<&str>) -> impl Display {
+ fmt::from_fn(move |f| write!(f, "{}", playground_button.unwrap_or_default()))
}
/// How a span of text is classified. Mostly corresponds to token kinds.
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 4addf2c3c9644..7065de14c8ea7 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -321,31 +321,34 @@ impl<'a, I: Iterator- >> Iterator for CodeBlocks<'_, 'a, I> {
))
});
- let tooltip = if ignore == Ignore::All {
- highlight::Tooltip::IgnoreAll
- } else if let Ignore::Some(platforms) = ignore {
- highlight::Tooltip::IgnoreSome(platforms)
- } else if compile_fail {
- highlight::Tooltip::CompileFail
- } else if should_panic {
- highlight::Tooltip::ShouldPanic
- } else if explicit_edition {
- highlight::Tooltip::Edition(edition)
- } else {
- highlight::Tooltip::None
+ let tooltip = {
+ use highlight::Tooltip::*;
+
+ if ignore == Ignore::All {
+ Some(IgnoreAll)
+ } else if let Ignore::Some(platforms) = ignore {
+ Some(IgnoreSome(platforms))
+ } else if compile_fail {
+ Some(CompileFail)
+ } else if should_panic {
+ Some(ShouldPanic)
+ } else if explicit_edition {
+ Some(Edition(edition))
+ } else {
+ None
+ }
};
// insert newline to clearly separate it from the
// previous block so we can shorten the html output
- let mut s = String::new();
- s.push('\n');
-
- highlight::render_example_with_highlighting(
- &text,
- &mut s,
- tooltip,
- playground_button.as_deref(),
- &added_classes,
+ let s = format!(
+ "\n{}",
+ highlight::render_example_with_highlighting(
+ &text,
+ tooltip.as_ref(),
+ playground_button.as_deref(),
+ &added_classes,
+ )
);
Some(Event::Html(s.into()))
}