Skip to content

Commit d7aa67f

Browse files
Auto merge of #148021 - GuillaumeGomez:simplify-mod-render, r=<try>
[rustdoc] Simplify module rendering and HTML tags handling
2 parents 6501e64 + 90c047b commit d7aa67f

File tree

1 file changed

+141
-143
lines changed

1 file changed

+141
-143
lines changed

src/librustdoc/html/render/print_item.rs

Lines changed: 141 additions & 143 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::iter;
55
use askama::Template;
66
use rustc_abi::VariantIdx;
77
use rustc_ast::join_path_syms;
8-
use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
8+
use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
99
use rustc_hir as hir;
1010
use rustc_hir::def::CtorKind;
1111
use rustc_hir::def_id::DefId;
@@ -307,8 +307,12 @@ fn item_module(cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) -> i
307307
fmt::from_fn(|w| {
308308
write!(w, "{}", document(cx, item, None, HeadingOffset::H2))?;
309309

310-
let mut not_stripped_items =
311-
items.iter().filter(|i| !i.is_stripped()).enumerate().collect::<Vec<_>>();
310+
let mut not_stripped_items: FxIndexMap<ItemType, Vec<(usize, &clean::Item)>> =
311+
FxIndexMap::default();
312+
313+
for (index, item) in items.iter().filter(|i| !i.is_stripped()).enumerate() {
314+
not_stripped_items.entry(item.type_()).or_default().push((index, item));
315+
}
312316

313317
// the order of item types in the listing
314318
fn reorder(ty: ItemType) -> u8 {
@@ -331,11 +335,6 @@ fn item_module(cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) -> i
331335
}
332336

333337
fn cmp(i1: &clean::Item, i2: &clean::Item, tcx: TyCtxt<'_>) -> Ordering {
334-
let rty1 = reorder(i1.type_());
335-
let rty2 = reorder(i2.type_());
336-
if rty1 != rty2 {
337-
return rty1.cmp(&rty2);
338-
}
339338
let is_stable1 =
340339
i1.stability(tcx).as_ref().map(|s| s.level.is_stable()).unwrap_or(true);
341340
let is_stable2 =
@@ -357,7 +356,9 @@ fn item_module(cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) -> i
357356

358357
match cx.shared.module_sorting {
359358
ModuleSorting::Alphabetical => {
360-
not_stripped_items.sort_by(|(_, i1), (_, i2)| cmp(i1, i2, tcx));
359+
for items in not_stripped_items.values_mut() {
360+
items.sort_by(|(_, i1), (_, i2)| cmp(i1, i2, tcx));
361+
}
361362
}
362363
ModuleSorting::DeclarationOrder => {}
363364
}
@@ -380,155 +381,152 @@ fn item_module(cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) -> i
380381
// can be identical even if the elements are different (mostly in imports).
381382
// So in case this is an import, we keep everything by adding a "unique id"
382383
// (which is the position in the vector).
383-
not_stripped_items.dedup_by_key(|(idx, i)| {
384-
(
385-
i.item_id,
386-
if i.name.is_some() { Some(full_path(cx, i)) } else { None },
387-
i.type_(),
388-
if i.is_import() { *idx } else { 0 },
389-
)
390-
});
384+
for items in not_stripped_items.values_mut() {
385+
items.dedup_by_key(|(idx, i)| {
386+
(
387+
i.item_id,
388+
if i.name.is_some() { Some(full_path(cx, i)) } else { None },
389+
i.type_(),
390+
if i.is_import() { *idx } else { 0 },
391+
)
392+
});
393+
}
391394

392395
debug!("{not_stripped_items:?}");
393-
let mut last_section = None;
394396

395-
for (_, myitem) in &not_stripped_items {
396-
let my_section = item_ty_to_section(myitem.type_());
397-
if Some(my_section) != last_section {
398-
if last_section.is_some() {
399-
w.write_str(ITEM_TABLE_CLOSE)?;
400-
}
401-
last_section = Some(my_section);
402-
let section_id = my_section.id();
403-
let tag =
404-
if section_id == "reexports" { REEXPORTS_TABLE_OPEN } else { ITEM_TABLE_OPEN };
405-
write!(
406-
w,
407-
"{}",
408-
write_section_heading(my_section.name(), &cx.derive_id(section_id), None, tag)
409-
)?;
410-
}
411-
412-
match myitem.kind {
413-
clean::ExternCrateItem { ref src } => {
414-
use crate::html::format::print_anchor;
397+
let mut types = not_stripped_items.keys().copied().collect::<Vec<_>>();
398+
types.sort_unstable_by(|a, b| reorder(*a).cmp(&reorder(*b)));
415399

416-
match *src {
417-
Some(src) => {
418-
write!(
419-
w,
420-
"<dt><code>{}extern crate {} as {};",
421-
visibility_print_with_space(myitem, cx),
422-
print_anchor(myitem.item_id.expect_def_id(), src, cx),
423-
EscapeBodyTextWithWbr(myitem.name.unwrap().as_str())
424-
)?;
425-
}
426-
None => {
427-
write!(
428-
w,
429-
"<dt><code>{}extern crate {};",
430-
visibility_print_with_space(myitem, cx),
431-
print_anchor(
432-
myitem.item_id.expect_def_id(),
433-
myitem.name.unwrap(),
434-
cx
435-
)
436-
)?;
437-
}
438-
}
439-
w.write_str("</code></dt>")?;
440-
}
400+
for type_ in types {
401+
let my_section = item_ty_to_section(type_);
402+
let tag = if my_section == super::ItemSection::Reexports {
403+
REEXPORTS_TABLE_OPEN
404+
} else {
405+
ITEM_TABLE_OPEN
406+
};
407+
write!(
408+
w,
409+
"{}",
410+
write_section_heading(my_section.name(), &cx.derive_id(my_section.id()), None, tag)
411+
)?;
441412

442-
clean::ImportItem(ref import) => {
443-
let stab_tags = import.source.did.map_or_else(String::new, |import_def_id| {
444-
print_extra_info_tags(tcx, myitem, item, Some(import_def_id)).to_string()
445-
});
413+
for (_, myitem) in &not_stripped_items[&type_] {
414+
match myitem.kind {
415+
clean::ExternCrateItem { ref src } => {
416+
use crate::html::format::print_anchor;
446417

447-
let id = match import.kind {
448-
clean::ImportKind::Simple(s) => {
449-
format!(" id=\"{}\"", cx.derive_id(format!("reexport.{s}")))
418+
match *src {
419+
Some(src) => {
420+
write!(
421+
w,
422+
"<dt><code>{}extern crate {} as {};",
423+
visibility_print_with_space(myitem, cx),
424+
print_anchor(myitem.item_id.expect_def_id(), src, cx),
425+
EscapeBodyTextWithWbr(myitem.name.unwrap().as_str())
426+
)?;
427+
}
428+
None => {
429+
write!(
430+
w,
431+
"<dt><code>{}extern crate {};",
432+
visibility_print_with_space(myitem, cx),
433+
print_anchor(
434+
myitem.item_id.expect_def_id(),
435+
myitem.name.unwrap(),
436+
cx
437+
)
438+
)?;
439+
}
450440
}
451-
clean::ImportKind::Glob => String::new(),
452-
};
453-
write!(
454-
w,
455-
"<dt{id}>\
456-
<code>"
457-
)?;
458-
render_attributes_in_code(w, myitem, "", cx);
459-
write!(
460-
w,
461-
"{vis}{imp}</code>{stab_tags}\
462-
</dt>",
463-
vis = visibility_print_with_space(myitem, cx),
464-
imp = import.print(cx)
465-
)?;
466-
}
467-
468-
_ => {
469-
if myitem.name.is_none() {
470-
continue;
471441
}
472-
473-
let unsafety_flag = match myitem.kind {
474-
clean::FunctionItem(_) | clean::ForeignFunctionItem(..)
475-
if myitem.fn_header(tcx).unwrap().safety
476-
== hir::HeaderSafety::Normal(hir::Safety::Unsafe) =>
477-
{
478-
"<sup title=\"unsafe function\">⚠</sup>"
479-
}
480-
clean::ForeignStaticItem(_, hir::Safety::Unsafe) => {
481-
"<sup title=\"unsafe static\">⚠</sup>"
482-
}
483-
_ => "",
484-
};
485-
486-
let visibility_and_hidden = match myitem.visibility(tcx) {
487-
Some(ty::Visibility::Restricted(_)) => {
488-
if myitem.is_doc_hidden() {
489-
// Don't separate with a space when there are two of them
490-
"<span title=\"Restricted Visibility\">&nbsp;🔒</span><span title=\"Hidden item\">👻</span> "
491-
} else {
492-
"<span title=\"Restricted Visibility\">&nbsp;🔒</span> "
442+
clean::ImportItem(ref import) => {
443+
let stab_tags =
444+
import.source.did.map_or_else(String::new, |import_def_id| {
445+
print_extra_info_tags(tcx, myitem, item, Some(import_def_id))
446+
.to_string()
447+
});
448+
let id = match import.kind {
449+
clean::ImportKind::Simple(s) => {
450+
format!(" id=\"{}\"", cx.derive_id(format!("reexport.{s}")))
493451
}
452+
clean::ImportKind::Glob => String::new(),
453+
};
454+
write!(
455+
w,
456+
"<dt{id}>\
457+
<code>"
458+
)?;
459+
render_attributes_in_code(w, myitem, "", cx);
460+
write!(
461+
w,
462+
"{vis}{imp}</code>{stab_tags}\
463+
</dt>",
464+
vis = visibility_print_with_space(myitem, cx),
465+
imp = import.print(cx)
466+
)?;
467+
}
468+
_ => {
469+
if myitem.name.is_none() {
470+
continue;
494471
}
495-
_ if myitem.is_doc_hidden() => {
496-
"<span title=\"Hidden item\">&nbsp;👻</span> "
497-
}
498-
_ => "",
499-
};
500472

501-
let docs =
502-
MarkdownSummaryLine(&myitem.doc_value(), &myitem.links(cx)).into_string();
503-
let (docs_before, docs_after) =
504-
if docs.is_empty() { ("", "") } else { ("<dd>", "</dd>") };
505-
write!(
506-
w,
507-
"<dt>\
508-
<a class=\"{class}\" href=\"{href}\" title=\"{title1} {title2}\">\
509-
{name}\
510-
</a>\
511-
{visibility_and_hidden}\
512-
{unsafety_flag}\
513-
{stab_tags}\
514-
</dt>\
515-
{docs_before}{docs}{docs_after}",
516-
name = EscapeBodyTextWithWbr(myitem.name.unwrap().as_str()),
517-
visibility_and_hidden = visibility_and_hidden,
518-
stab_tags = print_extra_info_tags(tcx, myitem, item, None),
519-
class = myitem.type_(),
520-
unsafety_flag = unsafety_flag,
521-
href = print_item_path(myitem.type_(), myitem.name.unwrap().as_str()),
522-
title1 = myitem.type_(),
523-
title2 = full_path(cx, myitem),
524-
)?;
473+
let unsafety_flag = match myitem.kind {
474+
clean::FunctionItem(_) | clean::ForeignFunctionItem(..)
475+
if myitem.fn_header(tcx).unwrap().safety
476+
== hir::HeaderSafety::Normal(hir::Safety::Unsafe) =>
477+
{
478+
"<sup title=\"unsafe function\">⚠</sup>"
479+
}
480+
clean::ForeignStaticItem(_, hir::Safety::Unsafe) => {
481+
"<sup title=\"unsafe static\">⚠</sup>"
482+
}
483+
_ => "",
484+
};
485+
let visibility_and_hidden = match myitem.visibility(tcx) {
486+
Some(ty::Visibility::Restricted(_)) => {
487+
if myitem.is_doc_hidden() {
488+
// Don't separate with a space when there are two of them
489+
"<span title=\"Restricted Visibility\">&nbsp;🔒</span><span title=\"Hidden item\">👻</span> "
490+
} else {
491+
"<span title=\"Restricted Visibility\">&nbsp;🔒</span> "
492+
}
493+
}
494+
_ if myitem.is_doc_hidden() => {
495+
"<span title=\"Hidden item\">&nbsp;👻</span> "
496+
}
497+
_ => "",
498+
};
499+
500+
let docs = MarkdownSummaryLine(&myitem.doc_value(), &myitem.links(cx))
501+
.into_string();
502+
let (docs_before, docs_after) =
503+
if docs.is_empty() { ("", "") } else { ("<dd>", "</dd>") };
504+
write!(
505+
w,
506+
"<dt>\
507+
<a class=\"{class}\" href=\"{href}\" title=\"{title1} {title2}\">\
508+
{name}\
509+
</a>\
510+
{visibility_and_hidden}\
511+
{unsafety_flag}\
512+
{stab_tags}\
513+
</dt>\
514+
{docs_before}{docs}{docs_after}",
515+
name = EscapeBodyTextWithWbr(myitem.name.unwrap().as_str()),
516+
visibility_and_hidden = visibility_and_hidden,
517+
stab_tags = print_extra_info_tags(tcx, myitem, item, None),
518+
class = type_,
519+
unsafety_flag = unsafety_flag,
520+
href = print_item_path(type_, myitem.name.unwrap().as_str()),
521+
title1 = myitem.type_(),
522+
title2 = full_path(cx, myitem),
523+
)?;
524+
}
525525
}
526526
}
527-
}
528-
529-
if last_section.is_some() {
530527
w.write_str(ITEM_TABLE_CLOSE)?;
531528
}
529+
532530
Ok(())
533531
})
534532
}

0 commit comments

Comments
 (0)