diff --git a/src/formatting/comment.rs b/src/formatting/comment.rs index 7115de2ec25..da326198735 100644 --- a/src/formatting/comment.rs +++ b/src/formatting/comment.rs @@ -156,6 +156,11 @@ pub(crate) fn is_last_comment_block(s: &str) -> bool { s.trim_end().ends_with("*/") } +/// Returns true if the first line of the passed string started with a block-comment. +pub(crate) fn is_first_comment_block(s: &str) -> bool { + s.trim_start().starts_with("/*") +} + /// Combine `prev_str` and `next_str` into a single `String`. `span` may contain /// comments between two strings. If there are such comments, then that will be /// recovered. If `allow_extend` is true and there is no comment between the two diff --git a/src/formatting/expr.rs b/src/formatting/expr.rs index 421f7ab6655..819d4abc8db 100644 --- a/src/formatting/expr.rs +++ b/src/formatting/expr.rs @@ -1205,7 +1205,7 @@ pub(crate) fn is_simple_block_stmt( && attrs.map_or(true, |a| a.is_empty()) } -fn block_has_statements(block: &ast::Block) -> bool { +pub(crate) fn block_has_statements(block: &ast::Block) -> bool { !block .stmts .iter() diff --git a/src/formatting/items.rs b/src/formatting/items.rs index b818732d23e..62b3839d578 100644 --- a/src/formatting/items.rs +++ b/src/formatting/items.rs @@ -18,7 +18,7 @@ use crate::formatting::{ FindUncommented, }, expr::{ - is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, rewrite_assign_rhs_with, + block_has_statements, is_simple_block_stmt, rewrite_assign_rhs, rewrite_assign_rhs_with, rewrite_assign_rhs_with_comments, RhsTactics, }, lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}, @@ -457,8 +457,15 @@ impl<'a> FmtVisitor<'a> { let context = self.get_context(); + let block_snip = self.snippet_provider.span_to_snippet(block.span)?; + let has_comments = if let Some(firstline_end) = block_snip.find('\n') { + contains_comment(&block_snip[firstline_end..]) + } else { + false + }; if self.config.empty_item_single_line() - && is_empty_block(&context, block, None) + && !block_has_statements(&block) + && !has_comments && self.block_indent.width() + fn_str.len() + 3 <= self.config.max_width() && !last_line_contains_single_line_comment(fn_str) { diff --git a/src/formatting/visitor.rs b/src/formatting/visitor.rs index 2a0af48c84a..0dfb6587f91 100644 --- a/src/formatting/visitor.rs +++ b/src/formatting/visitor.rs @@ -7,7 +7,10 @@ use rustc_span::{symbol, BytePos, Pos, Span, DUMMY_SP}; use crate::config::{BraceStyle, Config}; use crate::formatting::{ attr::*, - comment::{contains_comment, rewrite_comment, CodeCharKind, CommentCodeSlices}, + comment::{ + contains_comment, is_first_comment_block, is_last_comment_block, rewrite_comment, + CodeCharKind, CommentCodeSlices, + }, items::{ format_impl, format_trait, format_trait_alias, is_mod_decl, is_use_item, rewrite_associated_impl_type, rewrite_extern_crate, rewrite_opaque_impl_type, @@ -443,6 +446,39 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { if let Some((fn_str, fn_brace_style)) = rewrite { self.format_missing_with_indent(source!(self, s).lo()); + let mut last_pos = source!(self, block.span).lo(); + let block_snip = self.snippet(block.span); + if let Some(first_line) = block_snip.lines().next() { + let block_line_range = self.parse_sess.lookup_line_range(block.span); + let first_line_contains_stmt = if let Some(first_stmt) = block.stmts.first() { + self.parse_sess.lookup_line_range(first_stmt.span).lo == block_line_range.lo + } else { + false + }; + + let comment_snip = if block_line_range.lo == block_line_range.hi { + // 1= {, 1 = } + &first_line[1..first_line.len() - 1] + } else { + // 1= { + &first_line[1..] + }; + + if !first_line_contains_stmt + && contains_comment(comment_snip) + && (is_first_comment_block(comment_snip) && is_last_comment_block(comment_snip) + || !is_first_comment_block(comment_snip)) + { + if let Some(comment) = + rewrite_comment(comment_snip.trim(), false, self.shape(), self.config) + { + self.push_str(&comment); + self.push_str(&self.block_indent.to_string_with_newline(self.config)); + last_pos = last_pos + BytePos(comment_snip.len() as u32); + } + } + } + if let Some(rw) = self.single_line_fn(&fn_str, block, inner_attrs) { self.push_str(&rw); self.last_pos = s.hi(); @@ -457,7 +493,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } _ => unreachable!(), } - self.last_pos = source!(self, block.span).lo(); + self.last_pos = last_pos; } else { self.format_missing(source!(self, block.span).lo()); } diff --git a/tests/source/issue-3255.rs b/tests/source/issue-3255.rs new file mode 100644 index 00000000000..addf2754b3c --- /dev/null +++ b/tests/source/issue-3255.rs @@ -0,0 +1,51 @@ +fn foo(){ // Sample comment + 1 +} + +fn foo(){ + // Sample comment + 1 +} + +// Sample comment +fn foo(){ + 1 +} + +fn bar(){ +fn foo(){ // Sample comment + 1 +} +} + +fn foo( + param: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, + param2: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + ) { // Sample comment +1 +} + +fn foo(){} // Sample comment + +fn foo(){ /* Sample comment */ + 1 +} + +fn foo(){ /* Sample comment */ } + +fn foo(){ /* Sample + comment */ + 1 +} + +fn foo(){ // Some comment +} + +// Test +fn main() {} + +fn main() {/* Test */ let a =0; let b=1;} + +fn foo(){ // Ends with } + +} diff --git a/tests/target/comment.rs b/tests/target/comment.rs index b987c8a44f3..feb58328a96 100644 --- a/tests/target/comment.rs +++ b/tests/target/comment.rs @@ -59,8 +59,8 @@ fn issue_1086() { // random comment -fn main() { // Test -} +// Test +fn main() {} // #1643 fn some_fn() // some comment diff --git a/tests/target/issue-3255.rs b/tests/target/issue-3255.rs new file mode 100644 index 00000000000..e3a32b137c3 --- /dev/null +++ b/tests/target/issue-3255.rs @@ -0,0 +1,60 @@ +// Sample comment +fn foo() { + 1 +} + +fn foo() { + // Sample comment + 1 +} + +// Sample comment +fn foo() { + 1 +} + +fn bar() { + // Sample comment + fn foo() { + 1 + } +} + +// Sample comment +fn foo( + param: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, + param2: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, +) { + 1 +} + +fn foo() {} // Sample comment + +/* Sample comment */ +fn foo() { + 1 +} + +/* Sample comment */ +fn foo() {} + +fn foo() { + /* Sample + comment */ + 1 +} + +// Some comment +fn foo() {} + +// Test +fn main() {} + +fn main() { + /* Test */ + let a = 0; + let b = 1; +} + +// Ends with } +fn foo() {}