diff --git a/rustfmt-core/src/comment.rs b/rustfmt-core/src/comment.rs index 9c0322bcaeb1..dc0c59a617e9 100644 --- a/rustfmt-core/src/comment.rs +++ b/rustfmt-core/src/comment.rs @@ -214,11 +214,25 @@ pub fn combine_strs_with_missing_comments( )) } +pub fn rewrite_doc_comment(orig: &str, shape: Shape, config: &Config) -> Option { + _rewrite_comment(orig, false, shape, config, true) +} + pub fn rewrite_comment( orig: &str, block_style: bool, shape: Shape, config: &Config, +) -> Option { + _rewrite_comment(orig, block_style, shape, config, false) +} + +fn _rewrite_comment( + orig: &str, + block_style: bool, + shape: Shape, + config: &Config, + is_doc_comment: bool, ) -> Option { // If there are lines without a starting sigil, we won't format them correctly // so in that case we won't even re-align (if !config.normalize_comments()) and @@ -231,7 +245,7 @@ pub fn rewrite_comment( return Some(orig.to_owned()); } if !config.normalize_comments() && !config.wrap_comments() { - return light_rewrite_comment(orig, shape.indent, config); + return light_rewrite_comment(orig, shape.indent, config, is_doc_comment); } identify_comment(orig, block_style, shape, config) @@ -494,15 +508,29 @@ pub fn recover_missing_comment_in_span( } } +/// Trim trailing whitespaces unless they consist of two or more whitespaces. +fn trim_right_unless_two_whitespaces(s: &str, is_doc_comment: bool) -> &str { + if is_doc_comment && s.ends_with(" ") { + s + } else { + s.trim_right() + } +} + /// Trims whitespace and aligns to indent, but otherwise does not change comments. -fn light_rewrite_comment(orig: &str, offset: Indent, config: &Config) -> Option { +fn light_rewrite_comment( + orig: &str, + offset: Indent, + config: &Config, + is_doc_comment: bool, +) -> Option { let lines: Vec<&str> = orig.lines() .map(|l| { // This is basically just l.trim(), but in the case that a line starts // with `*` we want to leave one space before it, so it aligns with the // `*` in `/*`. let first_non_whitespace = l.find(|c| !char::is_whitespace(c)); - if let Some(fnw) = first_non_whitespace { + let left_trimmed = if let Some(fnw) = first_non_whitespace { if l.as_bytes()[fnw] == b'*' && fnw > 0 { &l[fnw - 1..] } else { @@ -510,7 +538,9 @@ fn light_rewrite_comment(orig: &str, offset: Indent, config: &Config) -> Option< } } else { "" - }.trim_right() + }; + // Preserve markdown's double-space line break syntax in doc comment. + trim_right_unless_two_whitespaces(left_trimmed, is_doc_comment) }) .collect(); Some(lines.join(&format!("\n{}", offset.to_string(config)))) diff --git a/rustfmt-core/src/visitor.rs b/rustfmt-core/src/visitor.rs index 0a0d59d0f02c..2d10be39d092 100644 --- a/rustfmt-core/src/visitor.rs +++ b/rustfmt-core/src/visitor.rs @@ -19,7 +19,7 @@ use syntax::parse::ParseSess; use codemap::{LineRangeUtils, SpanUtils}; use comment::{combine_strs_with_missing_comments, contains_comment, CodeCharKind, CommentCodeSlices, FindUncommented}; -use comment::rewrite_comment; +use comment::rewrite_doc_comment; use config::{BraceStyle, Config}; use expr::rewrite_literal; use items::{format_impl, format_trait, format_trait_alias, rewrite_associated_impl_type, @@ -892,7 +892,7 @@ impl Rewrite for ast::Attribute { .unwrap_or(0), ..shape }; - rewrite_comment(snippet, false, doc_shape, context.config) + rewrite_doc_comment(snippet, doc_shape, context.config) } else { if contains_comment(snippet) { return Some(snippet.to_owned()); @@ -957,7 +957,7 @@ fn rewrite_first_group_attrs( .join("\n"); return Some(( sugared_docs.len(), - rewrite_comment(&snippet, false, shape, context.config)?, + rewrite_doc_comment(&snippet, shape, context.config)?, )); } // Rewrite `#[derive(..)]`s. diff --git a/rustfmt-core/tests/source/markdown-comment.rs b/rustfmt-core/tests/source/markdown-comment.rs new file mode 100644 index 000000000000..1ec26562fe28 --- /dev/null +++ b/rustfmt-core/tests/source/markdown-comment.rs @@ -0,0 +1,15 @@ +// Preserve two trailing whitespaces in doc comment, +// but trim any whitespaces in normal comment. + +//! hello world +//! hello world + +/// hello world +/// hello world +/// hello world +fn foo() { + // hello world + // hello world + let x = 3; + println!("x = {}", x); +} diff --git a/rustfmt-core/tests/target/markdown-comment.rs b/rustfmt-core/tests/target/markdown-comment.rs new file mode 100644 index 000000000000..71a9921d2862 --- /dev/null +++ b/rustfmt-core/tests/target/markdown-comment.rs @@ -0,0 +1,15 @@ +// Preserve two trailing whitespaces in doc comment, +// but trim any whitespaces in normal comment. + +//! hello world +//! hello world + +/// hello world +/// hello world +/// hello world +fn foo() { + // hello world + // hello world + let x = 3; + println!("x = {}", x); +}