diff options
| author | Guillaume Gomez <guillaume1.gomez@gmail.com> | 2020-10-26 15:01:39 +0100 |
|---|---|---|
| committer | Guillaume Gomez <guillaume1.gomez@gmail.com> | 2020-10-26 21:34:53 +0100 |
| commit | 06fe27866920b3eaf6502f321ccb239cc617db10 (patch) | |
| tree | 13c9f46a3a91a3e06d3866e3e7ece84cc544ed48 /src | |
| parent | 07a63e6d1fabf3560e8e1e17c1d56b10a06152d9 (diff) | |
| download | rust-06fe27866920b3eaf6502f321ccb239cc617db10.tar.gz rust-06fe27866920b3eaf6502f321ccb239cc617db10.zip | |
Fix unindent behavior between different doc comments
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustdoc/passes/unindent_comments.rs | 131 |
1 files changed, 75 insertions, 56 deletions
diff --git a/src/librustdoc/passes/unindent_comments.rs b/src/librustdoc/passes/unindent_comments.rs index a9cf5a87f54..1c856b1da53 100644 --- a/src/librustdoc/passes/unindent_comments.rs +++ b/src/librustdoc/passes/unindent_comments.rs @@ -1,7 +1,6 @@ use std::cmp; -use std::string::String; -use crate::clean::{self, DocFragment, Item}; +use crate::clean::{self, DocFragment, DocFragmentKind, Item}; use crate::core::DocContext; use crate::fold::{self, DocFolder}; use crate::passes::Pass; @@ -35,65 +34,85 @@ impl clean::Attributes { } fn unindent_fragments(docs: &mut Vec<DocFragment>) { - for fragment in docs { - fragment.doc = unindent(&fragment.doc); - } -} - -fn unindent(s: &str) -> String { - let lines = s.lines().collect::<Vec<&str>>(); let mut saw_first_line = false; let mut saw_second_line = false; - let min_indent = lines.iter().fold(usize::MAX, |min_indent, line| { - // After we see the first non-whitespace line, look at - // the line we have. If it is not whitespace, and therefore - // part of the first paragraph, then ignore the indentation - // level of the first line - let ignore_previous_indents = - saw_first_line && !saw_second_line && !line.chars().all(|c| c.is_whitespace()); - - let min_indent = if ignore_previous_indents { usize::MAX } else { min_indent }; - - if saw_first_line { - saw_second_line = true; - } - if line.chars().all(|c| c.is_whitespace()) { - min_indent - } else { - saw_first_line = true; - let mut whitespace = 0; - line.chars().all(|char| { - // Compare against either space or tab, ignoring whether they - // are mixed or not - if char == ' ' || char == '\t' { - whitespace += 1; - true + let add = if !docs.windows(2).all(|arr| arr[0].kind == arr[1].kind) + && docs.iter().any(|d| d.kind == DocFragmentKind::SugaredDoc) + { + // In case we have a mix of sugared doc comments and "raw" ones, we want the sugared one to + // "decide" how much the minimum indent will be. + 1 + } else { + 0 + }; + + let min_indent = match docs + .iter() + .map(|fragment| { + fragment.doc.lines().fold(usize::MAX, |min_indent, line| { + // After we see the first non-whitespace line, look at + // the line we have. If it is not whitespace, and therefore + // part of the first paragraph, then ignore the indentation + // level of the first line + let ignore_previous_indents = + saw_first_line && !saw_second_line && !line.chars().all(|c| c.is_whitespace()); + + let min_indent = if ignore_previous_indents { usize::MAX } else { min_indent }; + + if saw_first_line { + saw_second_line = true; + } + + if line.chars().all(|c| c.is_whitespace()) { + min_indent } else { - false + saw_first_line = true; + // Compare against either space or tab, ignoring whether they are + // mixed or not. + let whitespace = line.chars().take_while(|c| *c == ' ' || *c == '\t').count(); + cmp::min(min_indent, whitespace) + + if fragment.kind == DocFragmentKind::SugaredDoc { 0 } else { add } } - }); - cmp::min(min_indent, whitespace) + }) + }) + .min() + { + Some(x) => x, + None => return, + }; + + let mut first_ignored = false; + for fragment in docs { + let lines: Vec<_> = fragment.doc.lines().collect(); + + if !lines.is_empty() { + let min_indent = if fragment.kind != DocFragmentKind::SugaredDoc && min_indent > 0 { + min_indent - add + } else { + min_indent + }; + + let mut iter = lines.iter(); + let mut result = if !first_ignored { + first_ignored = true; + vec![iter.next().unwrap().trim_start().to_string()] + } else { + Vec::new() + }; + result.extend_from_slice( + &iter + .map(|&line| { + if line.chars().all(|c| c.is_whitespace()) { + line.to_string() + } else { + assert!(line.len() >= min_indent); + line[min_indent..].to_string() + } + }) + .collect::<Vec<_>>(), + ); + fragment.doc = result.join("\n"); } - }); - - if !lines.is_empty() { - let mut unindented = vec![lines[0].trim_start().to_string()]; - unindented.extend_from_slice( - &lines[1..] - .iter() - .map(|&line| { - if line.chars().all(|c| c.is_whitespace()) { - line.to_string() - } else { - assert!(line.len() >= min_indent); - line[min_indent..].to_string() - } - }) - .collect::<Vec<_>>(), - ); - unindented.join("\n") - } else { - s.to_string() } } |
