Skip to content

Commit 06fe278

Browse files
Fix unindent behavior between different doc comments
1 parent 07a63e6 commit 06fe278

File tree

1 file changed

+75
-56
lines changed

1 file changed

+75
-56
lines changed
+75-56
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use std::cmp;
2-
use std::string::String;
32

4-
use crate::clean::{self, DocFragment, Item};
3+
use crate::clean::{self, DocFragment, DocFragmentKind, Item};
54
use crate::core::DocContext;
65
use crate::fold::{self, DocFolder};
76
use crate::passes::Pass;
@@ -35,65 +34,85 @@ impl clean::Attributes {
3534
}
3635

3736
fn unindent_fragments(docs: &mut Vec<DocFragment>) {
38-
for fragment in docs {
39-
fragment.doc = unindent(&fragment.doc);
40-
}
41-
}
42-
43-
fn unindent(s: &str) -> String {
44-
let lines = s.lines().collect::<Vec<&str>>();
4537
let mut saw_first_line = false;
4638
let mut saw_second_line = false;
47-
let min_indent = lines.iter().fold(usize::MAX, |min_indent, line| {
48-
// After we see the first non-whitespace line, look at
49-
// the line we have. If it is not whitespace, and therefore
50-
// part of the first paragraph, then ignore the indentation
51-
// level of the first line
52-
let ignore_previous_indents =
53-
saw_first_line && !saw_second_line && !line.chars().all(|c| c.is_whitespace());
54-
55-
let min_indent = if ignore_previous_indents { usize::MAX } else { min_indent };
56-
57-
if saw_first_line {
58-
saw_second_line = true;
59-
}
6039

61-
if line.chars().all(|c| c.is_whitespace()) {
62-
min_indent
63-
} else {
64-
saw_first_line = true;
65-
let mut whitespace = 0;
66-
line.chars().all(|char| {
67-
// Compare against either space or tab, ignoring whether they
68-
// are mixed or not
69-
if char == ' ' || char == '\t' {
70-
whitespace += 1;
71-
true
40+
let add = if !docs.windows(2).all(|arr| arr[0].kind == arr[1].kind)
41+
&& docs.iter().any(|d| d.kind == DocFragmentKind::SugaredDoc)
42+
{
43+
// In case we have a mix of sugared doc comments and "raw" ones, we want the sugared one to
44+
// "decide" how much the minimum indent will be.
45+
1
46+
} else {
47+
0
48+
};
49+
50+
let min_indent = match docs
51+
.iter()
52+
.map(|fragment| {
53+
fragment.doc.lines().fold(usize::MAX, |min_indent, line| {
54+
// After we see the first non-whitespace line, look at
55+
// the line we have. If it is not whitespace, and therefore
56+
// part of the first paragraph, then ignore the indentation
57+
// level of the first line
58+
let ignore_previous_indents =
59+
saw_first_line && !saw_second_line && !line.chars().all(|c| c.is_whitespace());
60+
61+
let min_indent = if ignore_previous_indents { usize::MAX } else { min_indent };
62+
63+
if saw_first_line {
64+
saw_second_line = true;
65+
}
66+
67+
if line.chars().all(|c| c.is_whitespace()) {
68+
min_indent
7269
} else {
73-
false
70+
saw_first_line = true;
71+
// Compare against either space or tab, ignoring whether they are
72+
// mixed or not.
73+
let whitespace = line.chars().take_while(|c| *c == ' ' || *c == '\t').count();
74+
cmp::min(min_indent, whitespace)
75+
+ if fragment.kind == DocFragmentKind::SugaredDoc { 0 } else { add }
7476
}
75-
});
76-
cmp::min(min_indent, whitespace)
77+
})
78+
})
79+
.min()
80+
{
81+
Some(x) => x,
82+
None => return,
83+
};
84+
85+
let mut first_ignored = false;
86+
for fragment in docs {
87+
let lines: Vec<_> = fragment.doc.lines().collect();
88+
89+
if !lines.is_empty() {
90+
let min_indent = if fragment.kind != DocFragmentKind::SugaredDoc && min_indent > 0 {
91+
min_indent - add
92+
} else {
93+
min_indent
94+
};
95+
96+
let mut iter = lines.iter();
97+
let mut result = if !first_ignored {
98+
first_ignored = true;
99+
vec![iter.next().unwrap().trim_start().to_string()]
100+
} else {
101+
Vec::new()
102+
};
103+
result.extend_from_slice(
104+
&iter
105+
.map(|&line| {
106+
if line.chars().all(|c| c.is_whitespace()) {
107+
line.to_string()
108+
} else {
109+
assert!(line.len() >= min_indent);
110+
line[min_indent..].to_string()
111+
}
112+
})
113+
.collect::<Vec<_>>(),
114+
);
115+
fragment.doc = result.join("\n");
77116
}
78-
});
79-
80-
if !lines.is_empty() {
81-
let mut unindented = vec![lines[0].trim_start().to_string()];
82-
unindented.extend_from_slice(
83-
&lines[1..]
84-
.iter()
85-
.map(|&line| {
86-
if line.chars().all(|c| c.is_whitespace()) {
87-
line.to_string()
88-
} else {
89-
assert!(line.len() >= min_indent);
90-
line[min_indent..].to_string()
91-
}
92-
})
93-
.collect::<Vec<_>>(),
94-
);
95-
unindented.join("\n")
96-
} else {
97-
s.to_string()
98117
}
99118
}

0 commit comments

Comments
 (0)