Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: remove multiple trailing lines in comments #6163

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 57 additions & 4 deletions src/comment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 10,8 @@ use crate::rewrite::RewriteContext;
use crate::shape::{Indent, Shape};
use crate::string::{rewrite_string, StringFormat};
use crate::utils::{
count_newlines, first_line_width, last_line_width, trim_left_preserve_layout,
trimmed_last_line_width, unicode_str_width,
count_newlines, first_line_width, is_horizontal_space, last_line_width,
trim_left_preserve_layout, trimmed_last_line_width, unicode_str_width,
};
use crate::{ErrorKind, FormattingError};

Expand Down Expand Up @@ -346,7 346,14 @@ fn identify_comment(
let (first_group, rest) = orig.split_at(first_group_ending);
let rewritten_first_group =
if !config.normalize_comments() && has_bare_lines && style.is_block_comment() {
trim_left_preserve_layout(first_group, shape.indent, config)?
let reindented = trim_left_preserve_layout(first_group, shape.indent, config)?;

// If wrap_comments is enabled, then remove any trailing blank lines
if config.wrap_comments() {
strip_comment_trailing_lines(reindented, style)
} else {
reindented
}
} else if !config.normalize_comments()
&& !config.wrap_comments()
&& !(
Expand Down Expand Up @@ -811,7 818,13 @@ impl<'a> CommentRewrite<'a> {
} else if self.is_prev_line_multi_line && !line.is_empty() {
self.result.push(' ')
} else if is_last && line.is_empty() {
// trailing blank lines are unwanted
// Trailing blank lines are unwanted; if the last line is blank, look for additional,
// preceding blank lines to remove, also.
let trailing_line = self.comment_line_separator.trim_end_matches(' ');
overhacked marked this conversation as resolved.
Show resolved Hide resolved
while self.result.ends_with(trailing_line) {
self.result
.truncate(self.result.len() - trailing_line.len());
}
if !self.closer.is_empty() {
self.result.push_str(&self.indent_str);
}
Expand Down Expand Up @@ -1047,6 1060,46 @@ fn trim_end_unless_two_whitespaces(s: &str, is_doc_comment: bool) -> &str {
}
}

/// Removes blank lines at the end of block comments
fn strip_comment_trailing_lines(comment: String, style: CommentStyle<'_>) -> String {
debug_assert!(
style.is_block_comment(),
"strip_suffix(style.closer()) ensures this function is a no-op on non-block comments"
);

// If final line is a normal closing line, look for trailing blank lines
if let Some(without_closer) = comment
.strip_suffix(style.closer())
.map(|s| s.trim_end_matches(is_horizontal_space))
.and_then(|s| s.strip_suffix('\n'))
{
let mut trimmed = without_closer.trim_end();
let closer_line = &comment[without_closer.len()..];
let line_start = style.line_start().trim_end();
// Start trimming trailing blank lines
loop {
// Remove any asterisk-prefixed or bare block comment lines
let t = trimmed.trim_end_matches(line_start).trim_end();
if t.len() == trimmed.len() {
// If no trimming occurred
break;
} else {
// ... otherwise, keep trying to trim
trimmed = t;
}
}

if without_closer.len() == trimmed.len() {
// No blank lines were removed
comment
} else {
trimmed.to_string() closer_line
}
} else {
// Final line either didn't have a closer or had non-whitespace along with the closer
comment
}
}
/// Trims whitespace and aligns to indent, but otherwise does not change comments.
fn light_rewrite_comment(
orig: &str,
Expand Down
4 changes: 4 additions & 0 deletions src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -675,6 675,10 @@ pub(crate) fn is_empty_line(s: &str) -> bool {
s.is_empty() || s.chars().all(char::is_whitespace)
}

pub(crate) fn is_horizontal_space(c: char) -> bool {
c == ' ' || c == '\t'
}

fn get_prefix_space_width(config: &Config, s: &str) -> usize {
let mut width = 0;
for c in s.chars() {
Expand Down
28 changes: 28 additions & 0 deletions tests/source/comment_trailing_lines.rs
Original file line number Diff line number Diff line change
@@ -0,0 1,28 @@
// rustfmt-wrap_comments: true

//! Module comment with multiple trailing lines
//!
//!

/// Doc comment with multiple trailing lines
///
///
pub mod foo {}

/// Doc comment with one trailing line
///
pub mod bar {}

/*
* Block comment with multiple trailing lines
*
*
*/
pub mod block {}
overhacked marked this conversation as resolved.
Show resolved Hide resolved

/**
Outer Block doc comment with multiple trailing lines


*/
pub mod outer_block_doc_comment {}
19 changes: 19 additions & 0 deletions tests/target/comment_trailing_lines.rs
Original file line number Diff line number Diff line change
@@ -0,0 1,19 @@
// rustfmt-wrap_comments: true

//! Module comment with multiple trailing lines

/// Doc comment with multiple trailing lines
pub mod foo {}

/// Doc comment with one trailing line
pub mod bar {}

/*
* Block comment with multiple trailing lines
*/
pub mod block {}

/**
Outer Block doc comment with multiple trailing lines
*/
pub mod outer_block_doc_comment {}
Loading