From 38167a806cd14dd744d4770c7e13ab2c5e44e69c Mon Sep 17 00:00:00 2001 From: vacuus Date: Sat, 18 Dec 2021 21:54:59 -0500 Subject: [PATCH 1/2] Omit check of a successive line in loop I think that s == "" is the only edge case (as it makes iter.next() return None the first time). The early return is necessary so that the last character of 'out' isn't popped if s == "" && !frag.need_backline --- src/librustdoc/clean/types.rs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 24e18bb3a51f4..0c60952f4500a 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -939,7 +939,13 @@ crate enum DocFragmentKind { // `need_backline` field). fn add_doc_fragment(out: &mut String, frag: &DocFragment) { let s = frag.doc.as_str(); - let mut iter = s.lines().peekable(); + let mut iter = s.lines(); + if s == "" { + if frag.need_backline { + out.push('\n'); + } + return; + } while let Some(line) = iter.next() { if line.chars().any(|c| !c.is_whitespace()) { assert!(line.len() >= frag.indent); @@ -947,13 +953,11 @@ fn add_doc_fragment(out: &mut String, frag: &DocFragment) { } else { out.push_str(line); } - if iter.peek().is_some() { - out.push('\n'); - } - } - if frag.need_backline { out.push('\n'); } + if !frag.need_backline { + out.pop(); + } } /// Collapse a collection of [`DocFragment`]s into one string, From 386ab1ed5ccc83b1fd5b50034929b3ee78b9ad15 Mon Sep 17 00:00:00 2001 From: Roc Yu Date: Sun, 19 Dec 2021 19:38:59 -0500 Subject: [PATCH 2/2] Remove 'need_backline' field of `DocFragment` --- src/librustdoc/clean/types.rs | 46 ++++++++----------- .../passes/unindent_comments/tests.rs | 1 - 2 files changed, 18 insertions(+), 29 deletions(-) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 0c60952f4500a..cb4896fbfd23d 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -914,7 +914,6 @@ crate struct DocFragment { crate parent_module: Option, crate doc: Symbol, crate kind: DocFragmentKind, - crate need_backline: bool, crate indent: usize, } @@ -930,20 +929,16 @@ crate enum DocFragmentKind { RawDoc, } -// The goal of this function is to apply the `DocFragment` transformations that are required when -// transforming into the final markdown. So the transformations in here are: -// -// * Applying the computed indent to each lines in each doc fragment (a `DocFragment` can contain -// multiple lines in case of `#[doc = ""]`). -// * Adding backlines between `DocFragment`s and adding an extra one if required (stored in the -// `need_backline` field). +/// The goal of this function is to apply the `DocFragment` transformation that is required when +/// transforming into the final Markdown, which is applying the computed indent to each line in +/// each doc fragment (a `DocFragment` can contain multiple lines in case of `#[doc = ""]`). +/// +/// Note: remove the trailing newline where appropriate fn add_doc_fragment(out: &mut String, frag: &DocFragment) { let s = frag.doc.as_str(); let mut iter = s.lines(); if s == "" { - if frag.need_backline { - out.push('\n'); - } + out.push('\n'); return; } while let Some(line) = iter.next() { @@ -955,9 +950,6 @@ fn add_doc_fragment(out: &mut String, frag: &DocFragment) { } out.push('\n'); } - if !frag.need_backline { - out.pop(); - } } /// Collapse a collection of [`DocFragment`]s into one string, @@ -967,6 +959,7 @@ crate fn collapse_doc_fragments(doc_strings: &[DocFragment]) -> String { for frag in doc_strings { add_doc_fragment(&mut acc, frag); } + acc.pop(); acc } @@ -1032,7 +1025,6 @@ impl Attributes { additional_attrs: Option<(&[ast::Attribute], DefId)>, ) -> Attributes { let mut doc_strings: Vec = vec![]; - let clean_attr = |(attr, parent_module): (&ast::Attribute, Option)| { if let Some(value) = attr.doc_str() { trace!("got doc_str={:?}", value); @@ -1043,18 +1035,8 @@ impl Attributes { DocFragmentKind::RawDoc }; - let frag = DocFragment { - span: attr.span, - doc: value, - kind, - parent_module, - need_backline: false, - indent: 0, - }; - - if let Some(prev) = doc_strings.last_mut() { - prev.need_backline = true; - } + let frag = + DocFragment { span: attr.span, doc: value, kind, parent_module, indent: 0 }; doc_strings.push(frag); @@ -1090,6 +1072,7 @@ impl Attributes { } add_doc_fragment(&mut out, new_frag); } + out.pop(); if out.is_empty() { None } else { Some(out) } } @@ -1098,10 +1081,17 @@ impl Attributes { /// The module can be different if this is a re-export with added documentation. crate fn collapsed_doc_value_by_module_level(&self) -> FxHashMap, String> { let mut ret = FxHashMap::default(); + if self.doc_strings.len() == 0 { + return ret; + } + let last_index = self.doc_strings.len() - 1; - for new_frag in self.doc_strings.iter() { + for (i, new_frag) in self.doc_strings.iter().enumerate() { let out = ret.entry(new_frag.parent_module).or_default(); add_doc_fragment(out, new_frag); + if i == last_index { + out.pop(); + } } ret } diff --git a/src/librustdoc/passes/unindent_comments/tests.rs b/src/librustdoc/passes/unindent_comments/tests.rs index 3d3d2e50321d9..baff839cdc88c 100644 --- a/src/librustdoc/passes/unindent_comments/tests.rs +++ b/src/librustdoc/passes/unindent_comments/tests.rs @@ -12,7 +12,6 @@ fn create_doc_fragment(s: &str) -> Vec { parent_module: None, doc: Symbol::intern(s), kind: DocFragmentKind::SugaredDoc, - need_backline: false, indent: 0, }] }