Rollup merge of #108757 - clubby789:askama-move, r=notriddle,jsha,GuillaumeGomez

rustdoc: Migrate `document_item_info` to Askama

https://rust-lang.zulipchat.com/#narrow/stream/266220-rustdoc/topic/rustdoc.20allocations.20are.20slow

Hoping to piece-by-piece migrate things to template. Had a few failed attempts at more complex parts of the code, so this is just a start.
This commit is contained in:
Matthias Krüger 2023-03-11 12:55:42 +01:00 committed by GitHub
commit 949c553100
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 84 additions and 43 deletions

View File

@ -46,6 +46,7 @@ use std::rc::Rc;
use std::str; use std::str;
use std::string::ToString; use std::string::ToString;
use askama::Template;
use rustc_ast_pretty::pprust; use rustc_ast_pretty::pprust;
use rustc_attr::{ConstStability, Deprecation, StabilityLevel}; use rustc_attr::{ConstStability, Deprecation, StabilityLevel};
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@ -418,7 +419,7 @@ fn document(
if let Some(ref name) = item.name { if let Some(ref name) = item.name {
info!("Documenting {}", name); info!("Documenting {}", name);
} }
document_item_info(w, cx, item, parent); document_item_info(cx, item, parent).render_into(w).unwrap();
if parent.is_none() { if parent.is_none() {
document_full_collapsible(w, item, cx, heading_offset); document_full_collapsible(w, item, cx, heading_offset);
} else { } else {
@ -460,7 +461,7 @@ fn document_short(
parent: &clean::Item, parent: &clean::Item,
show_def_docs: bool, show_def_docs: bool,
) { ) {
document_item_info(w, cx, item, Some(parent)); document_item_info(cx, item, Some(parent)).render_into(w).unwrap();
if !show_def_docs { if !show_def_docs {
return; return;
} }
@ -532,25 +533,23 @@ fn document_full_inner(
} }
} }
#[derive(Template)]
#[template(path = "item_info.html")]
struct ItemInfo {
items: Vec<ShortItemInfo>,
}
/// Add extra information about an item such as: /// Add extra information about an item such as:
/// ///
/// * Stability /// * Stability
/// * Deprecated /// * Deprecated
/// * Required features (through the `doc_cfg` feature) /// * Required features (through the `doc_cfg` feature)
fn document_item_info( fn document_item_info(
w: &mut Buffer,
cx: &mut Context<'_>, cx: &mut Context<'_>,
item: &clean::Item, item: &clean::Item,
parent: Option<&clean::Item>, parent: Option<&clean::Item>,
) { ) -> ItemInfo {
let item_infos = short_item_info(item, cx, parent); let items = short_item_info(item, cx, parent);
if !item_infos.is_empty() { ItemInfo { items }
w.write_str("<span class=\"item-info\">");
for info in item_infos {
w.write_str(&info);
}
w.write_str("</span>");
}
} }
fn portability(item: &clean::Item, parent: Option<&clean::Item>) -> Option<String> { fn portability(item: &clean::Item, parent: Option<&clean::Item>) -> Option<String> {
@ -568,7 +567,25 @@ fn portability(item: &clean::Item, parent: Option<&clean::Item>) -> Option<Strin
cfg cfg
); );
Some(format!("<div class=\"stab portability\">{}</div>", cfg?.render_long_html())) Some(cfg?.render_long_html())
}
#[derive(Template)]
#[template(path = "short_item_info.html")]
enum ShortItemInfo {
/// A message describing the deprecation of this item
Deprecation {
message: String,
},
/// The feature corresponding to an unstable item, and optionally
/// a tracking issue URL and number.
Unstable {
feature: String,
tracking: Option<(String, u32)>,
},
Portability {
message: String,
},
} }
/// Render the stability, deprecation and portability information that is displayed at the top of /// Render the stability, deprecation and portability information that is displayed at the top of
@ -577,7 +594,7 @@ fn short_item_info(
item: &clean::Item, item: &clean::Item,
cx: &mut Context<'_>, cx: &mut Context<'_>,
parent: Option<&clean::Item>, parent: Option<&clean::Item>,
) -> Vec<String> { ) -> Vec<ShortItemInfo> {
let mut extra_info = vec![]; let mut extra_info = vec![];
if let Some(depr @ Deprecation { note, since, is_since_rustc_version: _, suggestion: _ }) = if let Some(depr @ Deprecation { note, since, is_since_rustc_version: _, suggestion: _ }) =
@ -603,15 +620,10 @@ fn short_item_info(
if let Some(note) = note { if let Some(note) = note {
let note = note.as_str(); let note = note.as_str();
let html = MarkdownItemInfo(note, &mut cx.id_map); let html = MarkdownItemInfo(note, &mut cx.id_map);
message.push_str(&format!(": {}", html.into_string())); message.push_str(": ");
message.push_str(&html.into_string());
} }
extra_info.push(format!( extra_info.push(ShortItemInfo::Deprecation { message });
"<div class=\"stab deprecated\">\
<span class=\"emoji\">👎</span>\
<span>{}</span>\
</div>",
message,
));
} }
// Render unstable items. But don't render "rustc_private" crates (internal compiler crates). // Render unstable items. But don't render "rustc_private" crates (internal compiler crates).
@ -622,26 +634,17 @@ fn short_item_info(
.filter(|stab| stab.feature != sym::rustc_private) .filter(|stab| stab.feature != sym::rustc_private)
.map(|stab| (stab.level, stab.feature)) .map(|stab| (stab.level, stab.feature))
{ {
let mut message = "<span class=\"emoji\">🔬</span>\ let tracking = if let (Some(url), Some(issue)) = (&cx.shared.issue_tracker_base_url, issue)
<span>This is a nightly-only experimental API." {
.to_owned(); Some((url.clone(), issue.get()))
} else {
let mut feature = format!("<code>{}</code>", Escape(feature.as_str())); None
if let (Some(url), Some(issue)) = (&cx.shared.issue_tracker_base_url, issue) { };
feature.push_str(&format!( extra_info.push(ShortItemInfo::Unstable { feature: feature.to_string(), tracking });
"&nbsp;<a href=\"{url}{issue}\">#{issue}</a>",
url = url,
issue = issue
));
}
message.push_str(&format!(" ({})</span>", feature));
extra_info.push(format!("<div class=\"stab unstable\">{}</div>", message));
} }
if let Some(portability) = portability(item, parent) { if let Some(message) = portability(item, parent) {
extra_info.push(portability); extra_info.push(ShortItemInfo::Portability { message });
} }
extra_info extra_info
@ -1473,7 +1476,9 @@ fn render_impl(
// We need the stability of the item from the trait // We need the stability of the item from the trait
// because impls can't have a stability. // because impls can't have a stability.
if item.doc_value().is_some() { if item.doc_value().is_some() {
document_item_info(&mut info_buffer, cx, it, Some(parent)); document_item_info(cx, it, Some(parent))
.render_into(&mut info_buffer)
.unwrap();
document_full(&mut doc_buffer, item, cx, HeadingOffset::H5); document_full(&mut doc_buffer, item, cx, HeadingOffset::H5);
short_documented = false; short_documented = false;
} else { } else {
@ -1490,7 +1495,9 @@ fn render_impl(
} }
} }
} else { } else {
document_item_info(&mut info_buffer, cx, item, Some(parent)); document_item_info(cx, item, Some(parent))
.render_into(&mut info_buffer)
.unwrap();
if rendering_params.show_def_docs { if rendering_params.show_def_docs {
document_full(&mut doc_buffer, item, cx, HeadingOffset::H5); document_full(&mut doc_buffer, item, cx, HeadingOffset::H5);
short_documented = false; short_documented = false;
@ -1863,7 +1870,11 @@ pub(crate) fn render_impl_summary(
let is_trait = inner_impl.trait_.is_some(); let is_trait = inner_impl.trait_.is_some();
if is_trait { if is_trait {
if let Some(portability) = portability(&i.impl_item, Some(parent)) { if let Some(portability) = portability(&i.impl_item, Some(parent)) {
write!(w, "<span class=\"item-info\">{}</span>", portability); write!(
w,
"<span class=\"item-info\"><div class=\"stab portability\">{}</div></span>",
portability
);
} }
} }

View File

@ -0,0 +1,7 @@
{% if !items.is_empty() %}
<span class="item-info"> {# #}
{% for item in items %}
{{item|safe}} {# #}
{% endfor %}
</span>
{% endif %}

View File

@ -0,0 +1,23 @@
{% match self %}
{% when Self::Deprecation with { message } %}
<div class="stab deprecated"> {# #}
<span class="emoji">👎</span> {# #}
<span>{{message}}</span> {# #}
</div> {# #}
{% when Self::Unstable with { feature, tracking } %}
<div class="stab unstable"> {# #}
<span class="emoji">🔬</span> {# #}
<span> {# #}
This is a nightly-only experimental API. ({# #}
<code>{{feature}}</code> {# #}
{% match tracking %}
{% when Some with ((url, num)) %}
&nbsp;<a href="{{url}}{{num}}">#{{num}}</a> {# #}
{% when None %}
{% endmatch %}
) {# #}
</span> {# #}
</div> {# #}
{% when Self::Portability with { message } %}
<div class="stab portability">{{message|safe}}</div> {# #}
{% endmatch %}