Skip to content

Commit bf4a20c

Browse files
Generate section headings all from one place
1 parent d7c5358 commit bf4a20c

File tree

2 files changed

+68
-64
lines changed

2 files changed

+68
-64
lines changed

src/librustdoc/html/render/mod.rs

+17-3
Original file line numberDiff line numberDiff line change
@@ -1142,17 +1142,31 @@ impl<'a> AssocItemLink<'a> {
11421142
}
11431143
}
11441144

1145-
fn write_impl_section_heading(mut w: impl fmt::Write, title: &str, id: &str) {
1145+
pub fn write_section_heading(
1146+
w: &mut impl fmt::Write,
1147+
title: &str,
1148+
id: &str,
1149+
extra_class: Option<&str>,
1150+
extra: impl fmt::Display,
1151+
) {
1152+
let (extra_class, whitespace) = match extra_class {
1153+
Some(extra) => (extra, " "),
1154+
None => ("", ""),
1155+
};
11461156
write!(
11471157
w,
1148-
"<h2 id=\"{id}\" class=\"section-header\">\
1158+
"<h2 id=\"{id}\" class=\"{extra_class}{whitespace}section-header\">\
11491159
{title}\
11501160
<a href=\"#{id}\" class=\"anchor\">§</a>\
1151-
</h2>"
1161+
</h2>{extra}",
11521162
)
11531163
.unwrap();
11541164
}
11551165

1166+
fn write_impl_section_heading(w: &mut impl fmt::Write, title: &str, id: &str) {
1167+
write_section_heading(w, title, id, None, "")
1168+
}
1169+
11561170
pub(crate) fn render_all_impls(
11571171
mut w: impl Write,
11581172
cx: &mut Context<'_>,

src/librustdoc/html/render/print_item.rs

+51-61
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ use super::{
2222
item_ty_to_section, notable_traits_button, notable_traits_json, render_all_impls,
2323
render_assoc_item, render_assoc_items, render_attributes_in_code, render_attributes_in_pre,
2424
render_impl, render_rightside, render_stability_since_raw,
25-
render_stability_since_raw_with_extra, AssocItemLink, AssocItemRender, Context,
26-
ImplRenderingParameters, RenderMode,
25+
render_stability_since_raw_with_extra, write_section_heading, AssocItemLink, AssocItemRender,
26+
Context, ImplRenderingParameters, RenderMode,
2727
};
2828
use crate::clean;
2929
use crate::config::ModuleSorting;
@@ -428,13 +428,12 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items:
428428
w.write_str(ITEM_TABLE_CLOSE);
429429
}
430430
last_section = Some(my_section);
431-
write!(
431+
write_section_heading(
432432
w,
433-
"<h2 id=\"{id}\" class=\"section-header\">\
434-
{name}<a href=\"#{id}\" class=\"anchor\">§</a>\
435-
</h2>{ITEM_TABLE_OPEN}",
436-
id = cx.derive_id(my_section.id()),
437-
name = my_section.name(),
433+
my_section.name(),
434+
&cx.derive_id(my_section.id()),
435+
None,
436+
ITEM_TABLE_OPEN,
438437
);
439438
}
440439

@@ -824,16 +823,6 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
824823
// Trait documentation
825824
write!(w, "{}", document(cx, it, None, HeadingOffset::H2));
826825

827-
fn write_small_section_header(w: &mut Buffer, id: &str, title: &str, extra_content: &str) {
828-
write!(
829-
w,
830-
"<h2 id=\"{0}\" class=\"section-header\">\
831-
{1}<a href=\"#{0}\" class=\"anchor\">§</a>\
832-
</h2>{2}",
833-
id, title, extra_content
834-
)
835-
}
836-
837826
fn trait_item(w: &mut Buffer, cx: &mut Context<'_>, m: &clean::Item, t: &clean::Item) {
838827
let name = m.name.unwrap();
839828
info!("Documenting {name} on {ty_name:?}", ty_name = t.name);
@@ -867,10 +856,11 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
867856
}
868857

869858
if !required_types.is_empty() {
870-
write_small_section_header(
859+
write_section_heading(
871860
w,
872-
"required-associated-types",
873861
"Required Associated Types",
862+
"required-associated-types",
863+
None,
874864
"<div class=\"methods\">",
875865
);
876866
for t in required_types {
@@ -879,10 +869,11 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
879869
w.write_str("</div>");
880870
}
881871
if !provided_types.is_empty() {
882-
write_small_section_header(
872+
write_section_heading(
883873
w,
884-
"provided-associated-types",
885874
"Provided Associated Types",
875+
"provided-associated-types",
876+
None,
886877
"<div class=\"methods\">",
887878
);
888879
for t in provided_types {
@@ -892,10 +883,11 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
892883
}
893884

894885
if !required_consts.is_empty() {
895-
write_small_section_header(
886+
write_section_heading(
896887
w,
897-
"required-associated-consts",
898888
"Required Associated Constants",
889+
"required-associated-consts",
890+
None,
899891
"<div class=\"methods\">",
900892
);
901893
for t in required_consts {
@@ -904,10 +896,11 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
904896
w.write_str("</div>");
905897
}
906898
if !provided_consts.is_empty() {
907-
write_small_section_header(
899+
write_section_heading(
908900
w,
909-
"provided-associated-consts",
910901
"Provided Associated Constants",
902+
"provided-associated-consts",
903+
None,
911904
"<div class=\"methods\">",
912905
);
913906
for t in provided_consts {
@@ -918,10 +911,11 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
918911

919912
// Output the documentation for each function individually
920913
if !required_methods.is_empty() || must_implement_one_of_functions.is_some() {
921-
write_small_section_header(
914+
write_section_heading(
922915
w,
923-
"required-methods",
924916
"Required Methods",
917+
"required-methods",
918+
None,
925919
"<div class=\"methods\">",
926920
);
927921

@@ -939,10 +933,11 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
939933
w.write_str("</div>");
940934
}
941935
if !provided_methods.is_empty() {
942-
write_small_section_header(
936+
write_section_heading(
943937
w,
944-
"provided-methods",
945938
"Provided Methods",
939+
"provided-methods",
940+
None,
946941
"<div class=\"methods\">",
947942
);
948943
for m in provided_methods {
@@ -959,10 +954,11 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
959954
let mut extern_crates = FxHashSet::default();
960955

961956
if !t.is_object_safe(cx.tcx()) {
962-
write_small_section_header(
957+
write_section_heading(
963958
w,
964-
"object-safety",
965959
"Object Safety",
960+
"object-safety",
961+
None,
966962
&format!(
967963
"<div class=\"object-safety-info\">This trait is <b>not</b> \
968964
<a href=\"{base}/reference/items/traits.html#object-safety\">\
@@ -1006,7 +1002,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
10061002
foreign.sort_by_cached_key(|i| ImplString::new(i, cx));
10071003

10081004
if !foreign.is_empty() {
1009-
write_small_section_header(w, "foreign-impls", "Implementations on Foreign Types", "");
1005+
write_section_heading(w, "Implementations on Foreign Types", "foreign-impls", None, "");
10101006

10111007
for implementor in foreign {
10121008
let provided_methods = implementor.inner_impl().provided_trait_methods(tcx);
@@ -1031,10 +1027,11 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
10311027
}
10321028
}
10331029

1034-
write_small_section_header(
1030+
write_section_heading(
10351031
w,
1036-
"implementors",
10371032
"Implementors",
1033+
"implementors",
1034+
None,
10381035
"<div id=\"implementors-list\">",
10391036
);
10401037
for implementor in concrete {
@@ -1043,10 +1040,11 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
10431040
w.write_str("</div>");
10441041

10451042
if t.is_auto(tcx) {
1046-
write_small_section_header(
1043+
write_section_heading(
10471044
w,
1048-
"synthetic-implementors",
10491045
"Auto implementors",
1046+
"synthetic-implementors",
1047+
None,
10501048
"<div id=\"synthetic-implementors-list\">",
10511049
);
10521050
for implementor in synthetic {
@@ -1064,18 +1062,20 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
10641062
} else {
10651063
// even without any implementations to write in, we still want the heading and list, so the
10661064
// implementors javascript file pulled in below has somewhere to write the impls into
1067-
write_small_section_header(
1065+
write_section_heading(
10681066
w,
1069-
"implementors",
10701067
"Implementors",
1068+
"implementors",
1069+
None,
10711070
"<div id=\"implementors-list\"></div>",
10721071
);
10731072

10741073
if t.is_auto(tcx) {
1075-
write_small_section_header(
1074+
write_section_heading(
10761075
w,
1077-
"synthetic-implementors",
10781076
"Auto implementors",
1077+
"synthetic-implementors",
1078+
None,
10791079
"<div id=\"synthetic-implementors-list\"></div>",
10801080
);
10811081
}
@@ -1258,11 +1258,7 @@ fn item_type_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &c
12581258
write!(w, "{}", document(cx, it, None, HeadingOffset::H2));
12591259

12601260
if let Some(inner_type) = &t.inner_type {
1261-
write!(
1262-
w,
1263-
"<h2 id=\"aliased-type\" class=\"section-header\">\
1264-
Aliased Type<a href=\"#aliased-type\" class=\"anchor\">§</a></h2>"
1265-
);
1261+
write_section_heading(w, "Aliased Type", "aliased-type", None, "");
12661262

12671263
match inner_type {
12681264
clean::TypeAliasInnerType::Enum { variants, is_non_exhaustive } => {
@@ -1683,16 +1679,14 @@ fn item_variants(
16831679
enum_def_id: DefId,
16841680
) {
16851681
let tcx = cx.tcx();
1686-
write!(
1682+
write_section_heading(
16871683
w,
1688-
"<h2 id=\"variants\" class=\"variants section-header\">\
1689-
Variants{}<a href=\"#variants\" class=\"anchor\">§</a>\
1690-
</h2>\
1691-
{}\
1692-
<div class=\"variants\">",
1693-
document_non_exhaustive_header(it),
1694-
document_non_exhaustive(it)
1684+
&format!("Variants{}", document_non_exhaustive_header(it)),
1685+
"variants",
1686+
Some("variants"),
1687+
format!("{}<div class=\"variants\">", document_non_exhaustive(it)),
16951688
);
1689+
16961690
let should_show_enum_discriminant = should_show_enum_discriminant(cx, enum_def_id, variants);
16971691
for (index, variant) in variants.iter_enumerated() {
16981692
if variant.is_stripped() {
@@ -1933,16 +1927,12 @@ fn item_fields(
19331927
.peekable();
19341928
if let None | Some(CtorKind::Fn) = ctor_kind {
19351929
if fields.peek().is_some() {
1936-
write!(
1937-
w,
1938-
"<h2 id=\"fields\" class=\"fields section-header\">\
1939-
{}{}<a href=\"#fields\" class=\"anchor\">§</a>\
1940-
</h2>\
1941-
{}",
1930+
let title = format!(
1931+
"{}{}",
19421932
if ctor_kind.is_none() { "Fields" } else { "Tuple Fields" },
19431933
document_non_exhaustive_header(it),
1944-
document_non_exhaustive(it)
19451934
);
1935+
write_section_heading(w, &title, "fields", Some("fields"), document_non_exhaustive(it));
19461936
for (index, (field, ty)) in fields.enumerate() {
19471937
let field_name =
19481938
field.name.map_or_else(|| index.to_string(), |sym| sym.as_str().to_string());

0 commit comments

Comments
 (0)