Skip to content

Commit cade266

Browse files
committed
Auto merge of #111512 - petrochenkov:microdoc2, r=GuillaumeGomez
rustdoc: Cleanup doc string collapsing `doc_value` and (former) `collapsed_doc_value` can be implemented in terms of each other, and `doc_value` doesn't need the `Option`. This PR doesn't do any semantic changes, only refactoring, although some pre-existing choices between `doc_value` and `collapsed_doc_value` across rustdoc may be questionable.
2 parents d300bff + 4082053 commit cade266

17 files changed

+51
-84
lines changed

src/librustdoc/clean/types.rs

+24-41
Original file line numberDiff line numberDiff line change
@@ -401,12 +401,18 @@ impl Item {
401401
.unwrap_or_else(|| self.span(tcx).map_or(rustc_span::DUMMY_SP, |span| span.inner()))
402402
}
403403

404-
/// Finds the `doc` attribute as a NameValue and returns the corresponding
405-
/// value found.
406-
pub(crate) fn doc_value(&self) -> Option<String> {
404+
/// Combine all doc strings into a single value handling indentation and newlines as needed.
405+
pub(crate) fn doc_value(&self) -> String {
407406
self.attrs.doc_value()
408407
}
409408

409+
/// Combine all doc strings into a single value handling indentation and newlines as needed.
410+
/// Returns `None` is there's no documentation at all, and `Some("")` if there is some
411+
/// documentation but it is empty (e.g. `#[doc = ""]`).
412+
pub(crate) fn opt_doc_value(&self) -> Option<String> {
413+
self.attrs.opt_doc_value()
414+
}
415+
410416
pub(crate) fn from_def_id_and_parts(
411417
def_id: DefId,
412418
name: Option<Symbol>,
@@ -443,12 +449,6 @@ impl Item {
443449
}
444450
}
445451

446-
/// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
447-
/// with newlines.
448-
pub(crate) fn collapsed_doc_value(&self) -> Option<String> {
449-
self.attrs.collapsed_doc_value()
450-
}
451-
452452
pub(crate) fn links(&self, cx: &Context<'_>) -> Vec<RenderedLink> {
453453
use crate::html::format::{href, link_tooltip};
454454

@@ -1068,17 +1068,6 @@ impl<I: Iterator<Item = ast::NestedMetaItem>> NestedAttributesExt for I {
10681068
}
10691069
}
10701070

1071-
/// Collapse a collection of [`DocFragment`]s into one string,
1072-
/// handling indentation and newlines as needed.
1073-
pub(crate) fn collapse_doc_fragments(doc_strings: &[DocFragment]) -> String {
1074-
let mut acc = String::new();
1075-
for frag in doc_strings {
1076-
add_doc_fragment(&mut acc, frag);
1077-
}
1078-
acc.pop();
1079-
acc
1080-
}
1081-
10821071
/// A link that has not yet been rendered.
10831072
///
10841073
/// This link will be turned into a rendered link by [`Item::links`].
@@ -1163,29 +1152,23 @@ impl Attributes {
11631152
Attributes { doc_strings, other_attrs }
11641153
}
11651154

1166-
/// Finds the `doc` attribute as a NameValue and returns the corresponding
1167-
/// value found.
1168-
pub(crate) fn doc_value(&self) -> Option<String> {
1169-
let mut iter = self.doc_strings.iter();
1170-
1171-
let ori = iter.next()?;
1172-
let mut out = String::new();
1173-
add_doc_fragment(&mut out, ori);
1174-
for new_frag in iter {
1175-
add_doc_fragment(&mut out, new_frag);
1176-
}
1177-
out.pop();
1178-
if out.is_empty() { None } else { Some(out) }
1155+
/// Combine all doc strings into a single value handling indentation and newlines as needed.
1156+
pub(crate) fn doc_value(&self) -> String {
1157+
self.opt_doc_value().unwrap_or_default()
11791158
}
11801159

1181-
/// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
1182-
/// with newlines.
1183-
pub(crate) fn collapsed_doc_value(&self) -> Option<String> {
1184-
if self.doc_strings.is_empty() {
1185-
None
1186-
} else {
1187-
Some(collapse_doc_fragments(&self.doc_strings))
1188-
}
1160+
/// Combine all doc strings into a single value handling indentation and newlines as needed.
1161+
/// Returns `None` is there's no documentation at all, and `Some("")` if there is some
1162+
/// documentation but it is empty (e.g. `#[doc = ""]`).
1163+
pub(crate) fn opt_doc_value(&self) -> Option<String> {
1164+
(!self.doc_strings.is_empty()).then(|| {
1165+
let mut res = String::new();
1166+
for frag in &self.doc_strings {
1167+
add_doc_fragment(&mut res, frag);
1168+
}
1169+
res.pop();
1170+
res
1171+
})
11891172
}
11901173

11911174
pub(crate) fn get_doc_aliases(&self) -> Box<[Symbol]> {

src/librustdoc/clean/types/tests.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
use super::*;
22

3-
use crate::clean::collapse_doc_fragments;
4-
53
use rustc_resolve::rustdoc::{unindent_doc_fragments, DocFragment, DocFragmentKind};
64
use rustc_span::create_default_session_globals_then;
75
use rustc_span::source_map::DUMMY_SP;
@@ -22,7 +20,8 @@ fn run_test(input: &str, expected: &str) {
2220
create_default_session_globals_then(|| {
2321
let mut s = create_doc_fragment(input);
2422
unindent_doc_fragments(&mut s);
25-
assert_eq!(collapse_doc_fragments(&s), expected);
23+
let attrs = Attributes { doc_strings: s, other_attrs: Default::default() };
24+
assert_eq!(attrs.doc_value(), expected);
2625
});
2726
}
2827

src/librustdoc/core.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,7 @@ pub(crate) fn run_global_ctxt(
367367

368368
let mut krate = tcx.sess.time("clean_crate", || clean::krate(&mut ctxt));
369369

370-
if krate.module.doc_value().map(|d| d.is_empty()).unwrap_or(true) {
370+
if krate.module.doc_value().is_empty() {
371371
let help = format!(
372372
"The following guide may be of use:\n\
373373
{}/rustdoc/how-to-write-documentation.html",

src/librustdoc/doctest.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1237,7 +1237,7 @@ impl<'a, 'hir, 'tcx> HirCollector<'a, 'hir, 'tcx> {
12371237
// The collapse-docs pass won't combine sugared/raw doc attributes, or included files with
12381238
// anything else, this will combine them for us.
12391239
let attrs = Attributes::from_ast(ast_attrs);
1240-
if let Some(doc) = attrs.collapsed_doc_value() {
1240+
if let Some(doc) = attrs.opt_doc_value() {
12411241
// Use the outermost invocation, so that doctest names come from where the docs were written.
12421242
let span = ast_attrs
12431243
.iter()

src/librustdoc/formats/cache.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -327,9 +327,8 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
327327
// which should not be indexed. The crate-item itself is
328328
// inserted later on when serializing the search-index.
329329
if item.item_id.as_def_id().map_or(false, |idx| !idx.is_crate_root()) {
330-
let desc = item.doc_value().map_or_else(String::new, |x| {
331-
short_markdown_summary(x.as_str(), &item.link_names(self.cache))
332-
});
330+
let desc =
331+
short_markdown_summary(&item.doc_value(), &item.link_names(self.cache));
333332
let ty = item.type_();
334333
if ty != ItemType::StructField
335334
|| u16::from_str_radix(s.as_str(), 10).is_err()

src/librustdoc/html/render/context.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -184,11 +184,8 @@ impl<'tcx> Context<'tcx> {
184184
};
185185
title.push_str(" - Rust");
186186
let tyname = it.type_();
187-
let desc = it
188-
.doc_value()
189-
.as_ref()
190-
.map(|doc| plain_text_summary(doc, &it.link_names(&self.cache())));
191-
let desc = if let Some(desc) = desc {
187+
let desc = plain_text_summary(&it.doc_value(), &it.link_names(&self.cache()));
188+
let desc = if !desc.is_empty() {
192189
desc
193190
} else if it.is_crate() {
194191
format!("API documentation for the Rust `{}` crate.", self.shared.layout.krate)

src/librustdoc/html/render/mod.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -468,7 +468,8 @@ fn document_short<'a, 'cx: 'a>(
468468
if !show_def_docs {
469469
return Ok(());
470470
}
471-
if let Some(s) = item.doc_value() {
471+
let s = item.doc_value();
472+
if !s.is_empty() {
472473
let (mut summary_html, has_more_content) =
473474
MarkdownSummaryLine(&s, &item.links(cx)).into_string_with_has_more_content();
474475

@@ -511,7 +512,7 @@ fn document_full_inner<'a, 'cx: 'a>(
511512
heading_offset: HeadingOffset,
512513
) -> impl fmt::Display + 'a + Captures<'cx> {
513514
display_fn(move |f| {
514-
if let Some(s) = item.collapsed_doc_value() {
515+
if let Some(s) = item.opt_doc_value() {
515516
debug!("Doc block: =====\n{}\n=====", s);
516517
if is_collapsible {
517518
write!(
@@ -1476,7 +1477,7 @@ fn render_impl(
14761477
if let Some(it) = t.items.iter().find(|i| i.name == item.name) {
14771478
// We need the stability of the item from the trait
14781479
// because impls can't have a stability.
1479-
if item.doc_value().is_some() {
1480+
if !item.doc_value().is_empty() {
14801481
document_item_info(cx, it, Some(parent))
14811482
.render_into(&mut info_buffer)
14821483
.unwrap();
@@ -1747,7 +1748,7 @@ fn render_impl(
17471748
write!(w, "</summary>")
17481749
}
17491750

1750-
if let Some(ref dox) = i.impl_item.collapsed_doc_value() {
1751+
if let Some(ref dox) = i.impl_item.opt_doc_value() {
17511752
if trait_.is_none() && i.inner_impl().items.is_empty() {
17521753
w.write_str(
17531754
"<div class=\"item-info\">\

src/librustdoc/html/render/print_item.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -420,9 +420,9 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items:
420420
_ => "",
421421
};
422422

423-
let doc_value = myitem.doc_value().unwrap_or_default();
424423
w.write_str(ITEM_TABLE_ROW_OPEN);
425-
let docs = MarkdownSummaryLine(&doc_value, &myitem.links(cx)).into_string();
424+
let docs =
425+
MarkdownSummaryLine(&myitem.doc_value(), &myitem.links(cx)).into_string();
426426
let (docs_before, docs_after) = if docs.is_empty() {
427427
("", "")
428428
} else {
@@ -1338,7 +1338,7 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::
13381338
clean::VariantKind::Tuple(fields) => {
13391339
// Documentation on tuple variant fields is rare, so to reduce noise we only emit
13401340
// the section if at least one field is documented.
1341-
if fields.iter().any(|f| f.doc_value().is_some()) {
1341+
if fields.iter().any(|f| !f.doc_value().is_empty()) {
13421342
Some(("Tuple Fields", fields))
13431343
} else {
13441344
None

src/librustdoc/html/render/search_index.rs

+3-7
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,7 @@ pub(crate) fn build_index<'tcx>(
2828
// has since been learned.
2929
for &OrphanImplItem { parent, ref item, ref impl_generics } in &cache.orphan_impl_items {
3030
if let Some((fqp, _)) = cache.paths.get(&parent) {
31-
let desc = item
32-
.doc_value()
33-
.map_or_else(String::new, |s| short_markdown_summary(&s, &item.link_names(cache)));
31+
let desc = short_markdown_summary(&item.doc_value(), &item.link_names(cache));
3432
cache.search_index.push(IndexItem {
3533
ty: item.type_(),
3634
name: item.name.unwrap(),
@@ -45,10 +43,8 @@ pub(crate) fn build_index<'tcx>(
4543
}
4644
}
4745

48-
let crate_doc = krate
49-
.module
50-
.doc_value()
51-
.map_or_else(String::new, |s| short_markdown_summary(&s, &krate.module.link_names(cache)));
46+
let crate_doc =
47+
short_markdown_summary(&krate.module.doc_value(), &krate.module.link_names(cache));
5248

5349
// Aliases added through `#[doc(alias = "...")]`. Since a few items can have the same alias,
5450
// we need the alias element to have an array of items.

src/librustdoc/json/conversions.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ impl JsonRenderer<'_> {
4040
(String::from(&**link), id_from_item_default(id.into(), self.tcx))
4141
})
4242
.collect();
43-
let docs = item.attrs.collapsed_doc_value();
43+
let docs = item.opt_doc_value();
4444
let attrs = item.attributes(self.tcx, true);
4545
let span = item.span(self.tcx);
4646
let visibility = item.visibility(self.tcx);

src/librustdoc/passes/calculate_doc_coverage.rs

+1-7
Original file line numberDiff line numberDiff line change
@@ -206,13 +206,7 @@ impl<'a, 'b> DocVisitor for CoverageCalculator<'a, 'b> {
206206
let has_docs = !i.attrs.doc_strings.is_empty();
207207
let mut tests = Tests { found_tests: 0 };
208208

209-
find_testable_code(
210-
&i.attrs.collapsed_doc_value().unwrap_or_default(),
211-
&mut tests,
212-
ErrorCodes::No,
213-
false,
214-
None,
215-
);
209+
find_testable_code(&i.doc_value(), &mut tests, ErrorCodes::No, false, None);
216210

217211
let has_doc_example = tests.found_tests != 0;
218212
let hir_id = DocContext::as_local_hir_id(self.ctx.tcx, i.item_id).unwrap();

src/librustdoc/passes/check_doc_test_visibility.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,7 @@ pub(crate) fn check_doc_test_visibility(krate: Crate, cx: &mut DocContext<'_>) -
3434

3535
impl<'a, 'tcx> DocVisitor for DocTestVisibilityLinter<'a, 'tcx> {
3636
fn visit_item(&mut self, item: &Item) {
37-
let dox = item.attrs.collapsed_doc_value().unwrap_or_default();
38-
39-
look_for_tests(self.cx, &dox, item);
37+
look_for_tests(self.cx, &item.doc_value(), item);
4038

4139
self.visit_item_recur(item)
4240
}

src/librustdoc/passes/lint/bare_urls.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ pub(super) fn visit_item(cx: &DocContext<'_>, item: &Item) {
1818
// If non-local, no need to check anything.
1919
return;
2020
};
21-
let dox = item.attrs.collapsed_doc_value().unwrap_or_default();
21+
let dox = item.doc_value();
2222
if !dox.is_empty() {
2323
let report_diag = |cx: &DocContext<'_>, msg: &str, url: &str, range: Range<usize>| {
2424
let sp = source_span_for_markdown_range(cx.tcx, &dox, &range, &item.attrs)

src/librustdoc/passes/lint/check_code_block_syntax.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use crate::html::markdown::{self, RustCodeBlock};
1717
use crate::passes::source_span_for_markdown_range;
1818

1919
pub(crate) fn visit_item(cx: &DocContext<'_>, item: &clean::Item) {
20-
if let Some(dox) = &item.attrs.collapsed_doc_value() {
20+
if let Some(dox) = &item.opt_doc_value() {
2121
let sp = item.attr_span(cx.tcx);
2222
let extra = crate::html::markdown::ExtraInfo::new(cx.tcx, item.item_id.expect_def_id(), sp);
2323
for code_block in markdown::rust_code_blocks(dox, &extra) {

src/librustdoc/passes/lint/html_tags.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item) {
1515
let Some(hir_id) = DocContext::as_local_hir_id(tcx, item.item_id)
1616
// If non-local, no need to check anything.
1717
else { return };
18-
let dox = item.attrs.collapsed_doc_value().unwrap_or_default();
18+
let dox = item.doc_value();
1919
if !dox.is_empty() {
2020
let report_diag = |msg: &str, range: &Range<usize>, is_open_tag: bool| {
2121
let sp = match source_span_for_markdown_range(tcx, &dox, range, &item.attrs) {

src/librustdoc/passes/lint/unescaped_backticks.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item) {
1616
return;
1717
};
1818

19-
let dox = item.attrs.collapsed_doc_value().unwrap_or_default();
19+
let dox = item.doc_value();
2020
if dox.is_empty() {
2121
return;
2222
}

src/librustdoc/passes/stripper.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ impl<'a> DocFolder for ImplStripper<'a, '_> {
194194
})
195195
{
196196
return None;
197-
} else if imp.items.is_empty() && i.doc_value().is_none() {
197+
} else if imp.items.is_empty() && i.doc_value().is_empty() {
198198
return None;
199199
}
200200
}

0 commit comments

Comments
 (0)