Skip to content

Commit c18cd77

Browse files
[rustdoc] Simplify module rendering and HTML tags handling
1 parent 4b3ba58 commit c18cd77

File tree

1 file changed

+145
-143
lines changed

1 file changed

+145
-143
lines changed

src/librustdoc/html/render/print_item.rs

Lines changed: 145 additions & 143 deletions
Original file line numberDiff line numberDiff line change
@@ -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: FxHashMap<ItemType, Vec<(usize, &clean::Item)>> =
311+
FxHashMap::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 =
@@ -356,8 +355,12 @@ fn item_module(cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) -> i
356355
let tcx = cx.tcx();
357356

358357
match cx.shared.module_sorting {
359-
ModuleSorting::Alphabetical => {
360-
not_stripped_items.sort_by(|(_, i1), (_, i2)| cmp(i1, i2, tcx));
358+
ModuleSorting::Alphabetical =>
359+
{
360+
#[allow(rustc::potential_query_instability)]
361+
for items in not_stripped_items.values_mut() {
362+
items.sort_by(|(_, i1), (_, i2)| cmp(i1, i2, tcx));
363+
}
361364
}
362365
ModuleSorting::DeclarationOrder => {}
363366
}
@@ -380,155 +383,154 @@ fn item_module(cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) -> i
380383
// can be identical even if the elements are different (mostly in imports).
381384
// So in case this is an import, we keep everything by adding a "unique id"
382385
// (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-
});
386+
#[allow(rustc::potential_query_instability)]
387+
for items in not_stripped_items.values_mut() {
388+
items.dedup_by_key(|(idx, i)| {
389+
(
390+
i.item_id,
391+
if i.name.is_some() { Some(full_path(cx, i)) } else { None },
392+
i.type_(),
393+
if i.is_import() { *idx } else { 0 },
394+
)
395+
});
396+
}
391397

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

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-
}
400+
#[allow(rustc::potential_query_instability)]
401+
let mut types = not_stripped_items.keys().copied().collect::<Vec<_>>();
402+
types.sort_unstable_by(|a, b| reorder(*a).cmp(&reorder(*b)));
411403

412-
match myitem.kind {
413-
clean::ExternCrateItem { ref src } => {
414-
use crate::html::format::print_anchor;
415-
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-
}
404+
for type_ in types {
405+
let my_section = item_ty_to_section(type_);
406+
let tag = if my_section == super::ItemSection::Reexports {
407+
REEXPORTS_TABLE_OPEN
408+
} else {
409+
ITEM_TABLE_OPEN
410+
};
411+
write!(
412+
w,
413+
"{}",
414+
write_section_heading(my_section.name(), &cx.derive_id(my_section.id()), None, tag)
415+
)?;
441416

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-
});
417+
for (_, myitem) in &not_stripped_items[&type_] {
418+
match myitem.kind {
419+
clean::ExternCrateItem { ref src } => {
420+
use crate::html::format::print_anchor;
446421

447-
let id = match import.kind {
448-
clean::ImportKind::Simple(s) => {
449-
format!(" id=\"{}\"", cx.derive_id(format!("reexport.{s}")))
422+
match *src {
423+
Some(src) => {
424+
write!(
425+
w,
426+
"<dt><code>{}extern crate {} as {};",
427+
visibility_print_with_space(myitem, cx),
428+
print_anchor(myitem.item_id.expect_def_id(), src, cx),
429+
EscapeBodyTextWithWbr(myitem.name.unwrap().as_str())
430+
)?;
431+
}
432+
None => {
433+
write!(
434+
w,
435+
"<dt><code>{}extern crate {};",
436+
visibility_print_with_space(myitem, cx),
437+
print_anchor(
438+
myitem.item_id.expect_def_id(),
439+
myitem.name.unwrap(),
440+
cx
441+
)
442+
)?;
443+
}
450444
}
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;
471445
}
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> "
446+
clean::ImportItem(ref import) => {
447+
let stab_tags =
448+
import.source.did.map_or_else(String::new, |import_def_id| {
449+
print_extra_info_tags(tcx, myitem, item, Some(import_def_id))
450+
.to_string()
451+
});
452+
let id = match import.kind {
453+
clean::ImportKind::Simple(s) => {
454+
format!(" id=\"{}\"", cx.derive_id(format!("reexport.{s}")))
493455
}
456+
clean::ImportKind::Glob => String::new(),
457+
};
458+
write!(
459+
w,
460+
"<dt{id}>\
461+
<code>"
462+
)?;
463+
render_attributes_in_code(w, myitem, "", cx);
464+
write!(
465+
w,
466+
"{vis}{imp}</code>{stab_tags}\
467+
</dt>",
468+
vis = visibility_print_with_space(myitem, cx),
469+
imp = import.print(cx)
470+
)?;
471+
}
472+
_ => {
473+
if myitem.name.is_none() {
474+
continue;
494475
}
495-
_ if myitem.is_doc_hidden() => {
496-
"<span title=\"Hidden item\">&nbsp;👻</span> "
497-
}
498-
_ => "",
499-
};
500476

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

0 commit comments

Comments
 (0)