Skip to content

Commit 5cddd34

Browse files
authored
Preserve Markdown line breaks in inner and outer block doc comments (#4233)
1 parent d5d008d commit 5cddd34

File tree

4 files changed

+56
-17
lines changed

4 files changed

+56
-17
lines changed

src/formatting/comment.rs

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use crate::formatting::{
1212
string::{rewrite_string, StringFormat},
1313
utils::{
1414
count_newlines, first_line_width, last_line_width, tab_to_spaces,
15-
trim_left_preserve_layout, unicode_str_width,
15+
trim_end_unless_two_whitespaces, trim_left_preserve_layout, unicode_str_width,
1616
},
1717
};
1818

@@ -68,9 +68,13 @@ impl<'a> CommentStyle<'a> {
6868
}
6969

7070
/// Returns `true` if the commenting style is for documentation.
71+
/// https://doc.rust-lang.org/reference/comments.html
7172
pub(crate) fn is_doc_comment(&self) -> bool {
7273
match *self {
73-
CommentStyle::TripleSlash | CommentStyle::Doc => true,
74+
CommentStyle::TripleSlash
75+
| CommentStyle::Doc
76+
| CommentStyle::DoubleBullet
77+
| CommentStyle::Exclamation => true,
7478
_ => false,
7579
}
7680
}
@@ -244,6 +248,7 @@ pub(crate) fn combine_strs_with_missing_comments(
244248
}
245249

246250
pub(crate) fn rewrite_doc_comment(orig: &str, shape: Shape, config: &Config) -> Option<String> {
251+
debug!("rewrite_doc_comment: {:?}", orig);
247252
identify_comment(orig, false, shape, config, true)
248253
}
249254

@@ -253,6 +258,7 @@ pub(crate) fn rewrite_comment(
253258
shape: Shape,
254259
config: &Config,
255260
) -> Option<String> {
261+
debug!("rewrite_comment: {:?}", orig);
256262
identify_comment(orig, block_style, shape, config, false)
257263
}
258264

@@ -363,7 +369,7 @@ fn identify_comment(
363369
let (first_group, rest) = orig.split_at(first_group_ending);
364370
let rewritten_first_group =
365371
if !config.normalize_comments() && has_bare_lines && style.is_block_comment() {
366-
trim_left_preserve_layout(first_group, shape.indent, config)?
372+
trim_left_preserve_layout(first_group, shape.indent, config, is_doc_comment)?
367373
} else if !config.normalize_comments()
368374
&& !config.wrap_comments()
369375
&& !config.format_code_in_doc_comments()
@@ -926,15 +932,6 @@ pub(crate) fn recover_missing_comment_in_span(
926932
}
927933
}
928934

929-
/// Trim trailing whitespaces unless they consist of two or more whitespaces.
930-
fn trim_end_unless_two_whitespaces(s: &str, is_doc_comment: bool) -> &str {
931-
if is_doc_comment && s.ends_with(" ") {
932-
s
933-
} else {
934-
s.trim_end()
935-
}
936-
}
937-
938935
/// Trims whitespace and aligns to indent, but otherwise does not change comments.
939936
fn light_rewrite_comment(
940937
orig: &str,

src/formatting/macros.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,12 @@ fn return_macro_parse_failure_fallback(
180180
})
181181
.unwrap_or(false);
182182
if is_like_block_indent_style {
183-
return trim_left_preserve_layout(context.snippet(span), indent, &context.config);
183+
return trim_left_preserve_layout(
184+
context.snippet(span),
185+
indent,
186+
&context.config,
187+
/* inside_doc_comment */ false,
188+
);
184189
}
185190

186191
context
@@ -432,7 +437,12 @@ fn rewrite_macro_inner(
432437
// the `macro_name!` and `{ /* macro_body */ }` but skip modifying
433438
// anything in between the braces (for now).
434439
let snippet = context.snippet(mac.span()).trim_start_matches(|c| c != '{');
435-
match trim_left_preserve_layout(snippet, shape.indent, &context.config) {
440+
match trim_left_preserve_layout(
441+
snippet,
442+
shape.indent,
443+
&context.config,
444+
/* inside_doc_comment */ false,
445+
) {
436446
Some(macro_body) => Some(format!("{} {}", macro_name, macro_body)),
437447
None => Some(format!("{} {}", macro_name, snippet)),
438448
}

src/formatting/utils.rs

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -569,9 +569,12 @@ pub(crate) fn trim_left_preserve_layout(
569569
orig: &str,
570570
indent: Indent,
571571
config: &Config,
572+
inside_doc_comment: bool,
572573
) -> Option<String> {
573574
let mut lines = LineClasses::new(orig);
574-
let first_line = lines.next().map(|(_, s)| s.trim_end().to_owned())?;
575+
let first_line = lines
576+
.next()
577+
.map(|(_, s)| trim_end_unless_two_whitespaces(&s, inside_doc_comment).to_owned())?;
575578
let mut trimmed_lines = Vec::with_capacity(16);
576579

577580
let mut veto_trim = false;
@@ -593,7 +596,7 @@ pub(crate) fn trim_left_preserve_layout(
593596
trimmed = false;
594597
line
595598
} else {
596-
line.trim().to_owned()
599+
trim_end_unless_two_whitespaces(line.trim_start(), inside_doc_comment).to_owned()
597600
};
598601
trimmed_lines.push((trimmed, line, prefix_space_width));
599602

@@ -629,6 +632,16 @@ pub(crate) fn trim_left_preserve_layout(
629632
)
630633
}
631634

635+
/// Trim trailing whitespace unless it consists of two or more whitespaces and is in a doc comment.
636+
/// This is, needed to preserve Markdown's double-space line break syntax.
637+
pub(crate) fn trim_end_unless_two_whitespaces(s: &str, is_doc_comment: bool) -> &str {
638+
if is_doc_comment && s.ends_with(" ") {
639+
s
640+
} else {
641+
s.trim_end()
642+
}
643+
}
644+
632645
/// Based on the given line, determine if the next line can be indented or not.
633646
/// This allows to preserve the indentation of multi-line literals.
634647
pub(crate) fn indent_next_line(kind: FullCodeCharKind) -> bool {
@@ -687,8 +700,19 @@ mod test {
687700
let config = Config::default();
688701
let indent = Indent::new(4, 0);
689702
assert_eq!(
690-
trim_left_preserve_layout(&s, indent, &config),
703+
trim_left_preserve_layout(&s, indent, &config, false),
691704
Some("aaa\n bbb\n ccc".to_string())
692705
);
693706
}
707+
708+
#[test]
709+
fn test_trim_left_preserve_layout_no_trim_end_in_doc_comment() {
710+
let s = "aaa \n\tbbb \n ccc ";
711+
let config = Config::default();
712+
let indent = Indent::new(4, 0);
713+
assert_eq!(
714+
trim_left_preserve_layout(&s, indent, &config, true),
715+
Some("aaa \n bbb \n ccc ".to_string())
716+
);
717+
}
694718
}

tests/target/issue-3659.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/*! multiline doc-comment
2+
with trailing double space
3+
*/
4+
5+
/** multiline doc-comment
6+
with trailing double space
7+
*/
8+
fn foo() {}

0 commit comments

Comments
 (0)