mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-20 19:04:21 +00:00
Rollup merge of #99337 - jsha:simplify-highlight, r=GuillaumeGomez
rustdoc: simplify highlight.rs Split render_with_highlighting, which took many optional parameters, into three functions for specific purposes, which each take a smaller number of mostly required parameters. Remove some plumbing to pass through an "edition" parameter, which was used solely to avoid highlighting some 2021 Edition keywords in non-2021 code. I've tested a build of std docs before and after, and this does not change the generated HTML at all. Followup from https://github.com/rust-lang/rust/pull/91264#discussion_r901151101 r? ```@GuillaumeGomez```
This commit is contained in:
commit
9606408688
@ -33,27 +33,39 @@ pub(crate) struct HrefContext<'a, 'b, 'c> {
|
||||
|
||||
/// Decorations are represented as a map from CSS class to vector of character ranges.
|
||||
/// Each range will be wrapped in a span with that class.
|
||||
#[derive(Default)]
|
||||
pub(crate) struct DecorationInfo(pub(crate) FxHashMap<&'static str, Vec<(u32, u32)>>);
|
||||
|
||||
/// Highlights `src`, returning the HTML output.
|
||||
pub(crate) fn render_with_highlighting(
|
||||
#[derive(Eq, PartialEq, Clone, Copy)]
|
||||
pub(crate) enum Tooltip {
|
||||
Ignore,
|
||||
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 Buffer,
|
||||
class: Option<&str>,
|
||||
tooltip: Tooltip,
|
||||
playground_button: Option<&str>,
|
||||
tooltip: Option<(Option<Edition>, &str)>,
|
||||
edition: Edition,
|
||||
extra_content: Option<Buffer>,
|
||||
href_context: Option<HrefContext<'_, '_, '_>>,
|
||||
decoration_info: Option<DecorationInfo>,
|
||||
) {
|
||||
debug!("highlighting: ================\n{}\n==============", src);
|
||||
if let Some((edition_info, class)) = tooltip {
|
||||
let class = match tooltip {
|
||||
Tooltip::Ignore => " ignore",
|
||||
Tooltip::CompileFail => " compile_fail",
|
||||
Tooltip::ShouldPanic => " should_panic",
|
||||
Tooltip::Edition(_) => " edition",
|
||||
Tooltip::None => "",
|
||||
};
|
||||
|
||||
if tooltip != Tooltip::None {
|
||||
write!(
|
||||
out,
|
||||
"<div class='information'><div class='tooltip {}'{}>ⓘ</div></div>",
|
||||
"<div class='information'><div class='tooltip{}'{}>ⓘ</div></div>",
|
||||
class,
|
||||
if let Some(edition_info) = edition_info {
|
||||
if let Tooltip::Edition(edition_info) = tooltip {
|
||||
format!(" data-edition=\"{}\"", edition_info)
|
||||
} else {
|
||||
String::new()
|
||||
@ -61,20 +73,40 @@ pub(crate) fn render_with_highlighting(
|
||||
);
|
||||
}
|
||||
|
||||
write_header(out, class, extra_content);
|
||||
write_code(out, src, edition, href_context, decoration_info);
|
||||
write_header(out, &format!("rust-example-rendered{}", class), None);
|
||||
write_code(out, src, None, None);
|
||||
write_footer(out, playground_button);
|
||||
}
|
||||
|
||||
fn write_header(out: &mut Buffer, class: Option<&str>, extra_content: Option<Buffer>) {
|
||||
/// Highlights `src` as a macro, returning the HTML output.
|
||||
pub(crate) fn render_macro_with_highlighting(src: &str, out: &mut Buffer) {
|
||||
write_header(out, "macro", None);
|
||||
write_code(out, src, None, None);
|
||||
write_footer(out, None);
|
||||
}
|
||||
|
||||
/// Highlights `src` as a source code page, returning the HTML output.
|
||||
pub(crate) fn render_source_with_highlighting(
|
||||
src: &str,
|
||||
out: &mut Buffer,
|
||||
line_numbers: Buffer,
|
||||
href_context: HrefContext<'_, '_, '_>,
|
||||
decoration_info: DecorationInfo,
|
||||
) {
|
||||
write_header(out, "", Some(line_numbers));
|
||||
write_code(out, src, Some(href_context), Some(decoration_info));
|
||||
write_footer(out, None);
|
||||
}
|
||||
|
||||
fn write_header(out: &mut Buffer, class: &str, extra_content: Option<Buffer>) {
|
||||
write!(out, "<div class=\"example-wrap\">");
|
||||
if let Some(extra) = extra_content {
|
||||
out.push_buffer(extra);
|
||||
}
|
||||
if let Some(class) = class {
|
||||
write!(out, "<pre class=\"rust {}\">", class);
|
||||
} else {
|
||||
if class.is_empty() {
|
||||
write!(out, "<pre class=\"rust\">");
|
||||
} else {
|
||||
write!(out, "<pre class=\"rust {}\">", class);
|
||||
}
|
||||
write!(out, "<code>");
|
||||
}
|
||||
@ -93,7 +125,6 @@ fn write_header(out: &mut Buffer, class: Option<&str>, extra_content: Option<Buf
|
||||
fn write_code(
|
||||
out: &mut Buffer,
|
||||
src: &str,
|
||||
edition: Edition,
|
||||
href_context: Option<HrefContext<'_, '_, '_>>,
|
||||
decoration_info: Option<DecorationInfo>,
|
||||
) {
|
||||
@ -102,7 +133,6 @@ fn write_code(
|
||||
let mut closing_tags: Vec<&'static str> = Vec::new();
|
||||
Classifier::new(
|
||||
&src,
|
||||
edition,
|
||||
href_context.as_ref().map(|c| c.file_span).unwrap_or(DUMMY_SP),
|
||||
decoration_info,
|
||||
)
|
||||
@ -220,7 +250,7 @@ impl<'a> Iterator for TokenIter<'a> {
|
||||
}
|
||||
|
||||
/// Classifies into identifier class; returns `None` if this is a non-keyword identifier.
|
||||
fn get_real_ident_class(text: &str, edition: Edition, allow_path_keywords: bool) -> Option<Class> {
|
||||
fn get_real_ident_class(text: &str, allow_path_keywords: bool) -> Option<Class> {
|
||||
let ignore: &[&str] =
|
||||
if allow_path_keywords { &["self", "Self", "super", "crate"] } else { &["self", "Self"] };
|
||||
if ignore.iter().any(|k| *k == text) {
|
||||
@ -229,7 +259,7 @@ fn get_real_ident_class(text: &str, edition: Edition, allow_path_keywords: bool)
|
||||
Some(match text {
|
||||
"ref" | "mut" => Class::RefKeyWord,
|
||||
"false" | "true" => Class::Bool,
|
||||
_ if Symbol::intern(text).is_reserved(|| edition) => Class::KeyWord,
|
||||
_ if Symbol::intern(text).is_reserved(|| Edition::Edition2021) => Class::KeyWord,
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
@ -311,7 +341,6 @@ struct Classifier<'a> {
|
||||
in_attribute: bool,
|
||||
in_macro: bool,
|
||||
in_macro_nonterminal: bool,
|
||||
edition: Edition,
|
||||
byte_pos: u32,
|
||||
file_span: Span,
|
||||
src: &'a str,
|
||||
@ -321,12 +350,7 @@ struct Classifier<'a> {
|
||||
impl<'a> Classifier<'a> {
|
||||
/// Takes as argument the source code to HTML-ify, the rust edition to use and the source code
|
||||
/// file span which will be used later on by the `span_correspondance_map`.
|
||||
fn new(
|
||||
src: &str,
|
||||
edition: Edition,
|
||||
file_span: Span,
|
||||
decoration_info: Option<DecorationInfo>,
|
||||
) -> Classifier<'_> {
|
||||
fn new(src: &str, file_span: Span, decoration_info: Option<DecorationInfo>) -> Classifier<'_> {
|
||||
let tokens = PeekIter::new(TokenIter { src });
|
||||
let decorations = decoration_info.map(Decorations::new);
|
||||
Classifier {
|
||||
@ -334,7 +358,6 @@ impl<'a> Classifier<'a> {
|
||||
in_attribute: false,
|
||||
in_macro: false,
|
||||
in_macro_nonterminal: false,
|
||||
edition,
|
||||
byte_pos: 0,
|
||||
file_span,
|
||||
src,
|
||||
@ -354,7 +377,6 @@ impl<'a> Classifier<'a> {
|
||||
let start = self.byte_pos as usize;
|
||||
let mut pos = start;
|
||||
let mut has_ident = false;
|
||||
let edition = self.edition;
|
||||
|
||||
loop {
|
||||
let mut nb = 0;
|
||||
@ -376,7 +398,7 @@ impl<'a> Classifier<'a> {
|
||||
|
||||
if let Some((None, text)) = self.tokens.peek().map(|(token, text)| {
|
||||
if *token == TokenKind::Ident {
|
||||
let class = get_real_ident_class(text, edition, true);
|
||||
let class = get_real_ident_class(text, true);
|
||||
(class, text)
|
||||
} else {
|
||||
// Doesn't matter which Class we put in here...
|
||||
@ -634,7 +656,7 @@ impl<'a> Classifier<'a> {
|
||||
sink(Highlight::Token { text, class: None });
|
||||
return;
|
||||
}
|
||||
TokenKind::Ident => match get_real_ident_class(text, self.edition, false) {
|
||||
TokenKind::Ident => match get_real_ident_class(text, false) {
|
||||
None => match text {
|
||||
"Option" | "Result" => Class::PreludeTy,
|
||||
"Some" | "None" | "Ok" | "Err" => Class::PreludeVal,
|
||||
|
@ -3,7 +3,6 @@ use crate::html::format::Buffer;
|
||||
use expect_test::expect_file;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_span::create_default_session_globals_then;
|
||||
use rustc_span::edition::Edition;
|
||||
|
||||
const STYLE: &str = r#"
|
||||
<style>
|
||||
@ -23,7 +22,7 @@ fn test_html_highlighting() {
|
||||
let src = include_str!("fixtures/sample.rs");
|
||||
let html = {
|
||||
let mut out = Buffer::new();
|
||||
write_code(&mut out, src, Edition::Edition2018, None, None);
|
||||
write_code(&mut out, src, None, None);
|
||||
format!("{}<pre><code>{}</code></pre>\n", STYLE, out.into_inner())
|
||||
};
|
||||
expect_file!["fixtures/sample.html"].assert_eq(&html);
|
||||
@ -37,7 +36,7 @@ fn test_dos_backline() {
|
||||
println!(\"foo\");\r\n\
|
||||
}\r\n";
|
||||
let mut html = Buffer::new();
|
||||
write_code(&mut html, src, Edition::Edition2018, None, None);
|
||||
write_code(&mut html, src, None, None);
|
||||
expect_file!["fixtures/dos_line.html"].assert_eq(&html.into_inner());
|
||||
});
|
||||
}
|
||||
@ -51,7 +50,7 @@ let x = super::b::foo;
|
||||
let y = Self::whatever;";
|
||||
|
||||
let mut html = Buffer::new();
|
||||
write_code(&mut html, src, Edition::Edition2018, None, None);
|
||||
write_code(&mut html, src, None, None);
|
||||
expect_file!["fixtures/highlight.html"].assert_eq(&html.into_inner());
|
||||
});
|
||||
}
|
||||
@ -61,7 +60,7 @@ fn test_union_highlighting() {
|
||||
create_default_session_globals_then(|| {
|
||||
let src = include_str!("fixtures/union.rs");
|
||||
let mut html = Buffer::new();
|
||||
write_code(&mut html, src, Edition::Edition2018, None, None);
|
||||
write_code(&mut html, src, None, None);
|
||||
expect_file!["fixtures/union.html"].assert_eq(&html.into_inner());
|
||||
});
|
||||
}
|
||||
@ -75,7 +74,7 @@ let y = 2;";
|
||||
decorations.insert("example", vec![(0, 10)]);
|
||||
|
||||
let mut html = Buffer::new();
|
||||
write_code(&mut html, src, Edition::Edition2018, None, Some(DecorationInfo(decorations)));
|
||||
write_code(&mut html, src, None, Some(DecorationInfo(decorations)));
|
||||
expect_file!["fixtures/decorations.html"].assert_eq(&html.into_inner());
|
||||
});
|
||||
}
|
||||
|
@ -330,34 +330,27 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> {
|
||||
});
|
||||
|
||||
let tooltip = if ignore != Ignore::None {
|
||||
Some((None, "ignore"))
|
||||
highlight::Tooltip::Ignore
|
||||
} else if compile_fail {
|
||||
Some((None, "compile_fail"))
|
||||
highlight::Tooltip::CompileFail
|
||||
} else if should_panic {
|
||||
Some((None, "should_panic"))
|
||||
highlight::Tooltip::ShouldPanic
|
||||
} else if explicit_edition {
|
||||
Some((Some(edition), "edition"))
|
||||
highlight::Tooltip::Edition(edition)
|
||||
} else {
|
||||
None
|
||||
highlight::Tooltip::None
|
||||
};
|
||||
|
||||
// insert newline to clearly separate it from the
|
||||
// previous block so we can shorten the html output
|
||||
let mut s = Buffer::new();
|
||||
s.push_str("\n");
|
||||
highlight::render_with_highlighting(
|
||||
|
||||
highlight::render_example_with_highlighting(
|
||||
&text,
|
||||
&mut s,
|
||||
Some(&format!(
|
||||
"rust-example-rendered{}",
|
||||
if let Some((_, class)) = tooltip { format!(" {}", class) } else { String::new() }
|
||||
)),
|
||||
playground_button.as_deref(),
|
||||
tooltip,
|
||||
edition,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
playground_button.as_deref(),
|
||||
);
|
||||
Some(Event::Html(s.into_inner().into()))
|
||||
}
|
||||
|
@ -2773,11 +2773,10 @@ fn render_call_locations(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Ite
|
||||
sources::print_src(
|
||||
w,
|
||||
contents_subset,
|
||||
call_data.edition,
|
||||
file_span,
|
||||
cx,
|
||||
&root_path,
|
||||
Some(highlight::DecorationInfo(decoration_info)),
|
||||
highlight::DecorationInfo(decoration_info),
|
||||
sources::SourceContext::Embedded { offset: line_min },
|
||||
);
|
||||
write!(w, "</div></div>");
|
||||
|
@ -1322,17 +1322,7 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::
|
||||
|
||||
fn item_macro(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::Macro) {
|
||||
wrap_into_docblock(w, |w| {
|
||||
highlight::render_with_highlighting(
|
||||
&t.source,
|
||||
w,
|
||||
Some("macro"),
|
||||
None,
|
||||
None,
|
||||
it.span(cx.tcx()).inner().edition(),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
highlight::render_macro_with_highlighting(&t.source, w);
|
||||
});
|
||||
document(w, cx, it, None, HeadingOffset::H2)
|
||||
}
|
||||
|
@ -11,7 +11,6 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_hir::def_id::LOCAL_CRATE;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::Session;
|
||||
use rustc_span::edition::Edition;
|
||||
use rustc_span::source_map::FileName;
|
||||
|
||||
use std::ffi::OsStr;
|
||||
@ -213,11 +212,10 @@ impl SourceCollector<'_, '_> {
|
||||
print_src(
|
||||
buf,
|
||||
contents,
|
||||
cx.shared.edition(),
|
||||
file_span,
|
||||
cx,
|
||||
&root_path,
|
||||
None,
|
||||
highlight::DecorationInfo::default(),
|
||||
SourceContext::Standalone,
|
||||
)
|
||||
},
|
||||
@ -266,11 +264,10 @@ pub(crate) enum SourceContext {
|
||||
pub(crate) fn print_src(
|
||||
buf: &mut Buffer,
|
||||
s: &str,
|
||||
edition: Edition,
|
||||
file_span: rustc_span::Span,
|
||||
context: &Context<'_>,
|
||||
root_path: &str,
|
||||
decoration_info: Option<highlight::DecorationInfo>,
|
||||
decoration_info: highlight::DecorationInfo,
|
||||
source_context: SourceContext,
|
||||
) {
|
||||
let lines = s.lines().count();
|
||||
@ -289,15 +286,11 @@ pub(crate) fn print_src(
|
||||
}
|
||||
}
|
||||
line_numbers.write_str("</pre>");
|
||||
highlight::render_with_highlighting(
|
||||
highlight::render_source_with_highlighting(
|
||||
s,
|
||||
buf,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
edition,
|
||||
Some(line_numbers),
|
||||
Some(highlight::HrefContext { context, file_span, root_path }),
|
||||
line_numbers,
|
||||
highlight::HrefContext { context, file_span, root_path },
|
||||
decoration_info,
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user