diff --git a/src/expr.rs b/src/expr.rs index 7e1e3922d6a..16dfe6fcaa6 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -666,6 +666,7 @@ impl Rewrite for ast::Block { let mut visitor = FmtVisitor::from_codemap(context.parse_session, context.config); visitor.block_indent = shape.indent; + visitor.is_if_else_block = context.is_if_else_block; let prefix = match self.rules { ast::BlockCheckMode::Unsafe(..) => { @@ -965,7 +966,10 @@ impl<'a> Rewrite for ControlFlow<'a> { width: block_width, ..shape }; - let block_str = try_opt!(self.block.rewrite(context, block_shape)); + let mut block_context = context.clone(); + block_context.is_if_else_block = self.else_block.is_some(); + + let block_str = try_opt!(self.block.rewrite(&block_context, block_shape)); let cond_span = if let Some(cond) = self.cond { cond.span diff --git a/src/rewrite.rs b/src/rewrite.rs index 272e67756ab..9713871880e 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -27,7 +27,11 @@ pub struct RewriteContext<'a> { pub codemap: &'a CodeMap, pub config: &'a Config, pub inside_macro: bool, + // Force block indent style even if we are using visual indent style. pub use_block: bool, + // When `format_if_else_cond_comment` is true, unindent the comment on top + // of the `else` or `else if`. + pub is_if_else_block: bool, } impl<'a> RewriteContext<'a> { diff --git a/src/visitor.rs b/src/visitor.rs index affcbf6b082..33e9812ee1f 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -56,6 +56,7 @@ pub struct FmtVisitor<'a> { pub block_indent: Indent, pub config: &'a Config, pub failed: bool, + pub is_if_else_block: bool, } impl<'a> FmtVisitor<'a> { @@ -117,9 +118,22 @@ impl<'a> FmtVisitor<'a> { } } + let mut unindent_comment = self.is_if_else_block && !b.stmts.is_empty(); + if unindent_comment { + let end_pos = source!(self, b.span).hi - brace_compensation; + let snippet = self.get_context() + .snippet(codemap::mk_sp(self.last_pos, end_pos)); + unindent_comment = snippet.contains("//") || snippet.contains("/*"); + } // FIXME: we should compress any newlines here to just one + if unindent_comment { + self.block_indent = self.block_indent.block_unindent(self.config); + } self.format_missing_with_indent(source!(self, b.span).hi - brace_compensation); - self.close_block(); + if unindent_comment { + self.block_indent = self.block_indent.block_indent(self.config); + } + self.close_block(unindent_comment); self.last_pos = source!(self, b.span).hi; } @@ -127,9 +141,11 @@ impl<'a> FmtVisitor<'a> { // item in the block and the closing brace to the block's level. // The closing brace itself, however, should be indented at a shallower // level. - fn close_block(&mut self) { + fn close_block(&mut self, unindent_comment: bool) { let total_len = self.buffer.len; - let chars_too_many = if self.config.hard_tabs() { + let chars_too_many = if unindent_comment { + 0 + } else if self.config.hard_tabs() { 1 } else { self.config.tab_spaces() @@ -484,6 +500,7 @@ impl<'a> FmtVisitor<'a> { block_indent: Indent::empty(), config: config, failed: false, + is_if_else_block: false, } } @@ -587,7 +604,7 @@ impl<'a> FmtVisitor<'a> { self.block_indent = self.block_indent.block_indent(self.config); self.walk_mod_items(m); self.format_missing_with_indent(source!(self, m.inner).hi - BytePos(1)); - self.close_block(); + self.close_block(false); } self.last_pos = source!(self, m.inner).hi; } else { @@ -611,6 +628,7 @@ impl<'a> FmtVisitor<'a> { config: self.config, inside_macro: false, use_block: false, + is_if_else_block: false, } } } diff --git a/tests/target/unindent_if_else_cond_comment.rs b/tests/target/unindent_if_else_cond_comment.rs new file mode 100644 index 00000000000..98621b1eed1 --- /dev/null +++ b/tests/target/unindent_if_else_cond_comment.rs @@ -0,0 +1,27 @@ +// Comments on else block. See #1575. + +fn example() { + // `if` comment + if x { + foo(); + // `else if` comment + } else if y { + foo(); + // Comment on `else if`. + // Comment on `else if`. + } else if z { + bar(); + /* + * Multi line comment on `else if` + */ + } else if xx { + bar(); + /* Single line comment on `else if` */ + } else if yy { + foo(); + // `else` comment + } else { + foo(); + // Comment at the end of `else` block + }; +}