diff --git a/crates/oxc_formatter/src/utils/statement_body.rs b/crates/oxc_formatter/src/utils/statement_body.rs index b264683dd79dd..5c6043dc1cc27 100644 --- a/crates/oxc_formatter/src/utils/statement_body.rs +++ b/crates/oxc_formatter/src/utils/statement_body.rs @@ -37,9 +37,13 @@ impl<'a> Format<'a> for FormatStatementBody<'a, '_> { write!(f, empty); } else if let AstNodes::BlockStatement(block) = self.body.as_ast_nodes() { write!(f, [space()]); - // Use `write` instead of `format` to avoid printing leading comments of the block. - // Those comments should be printed inside the block statement. - block.write(f); + if matches!(self.body.parent, AstNodes::IfStatement(_)) { + write!(f, [block]); + } else { + // Use `write` instead of `format` to avoid printing leading comments of the block. + // Those comments should be printed inside the block statement. + block.write(f); + } } else if self.force_space { write!(f, [space(), self.body]); } else { diff --git a/crates/oxc_formatter/src/write/mod.rs b/crates/oxc_formatter/src/write/mod.rs index d598fe5fe0763..623d939558dc6 100644 --- a/crates/oxc_formatter/src/write/mod.rs +++ b/crates/oxc_formatter/src/write/mod.rs @@ -768,10 +768,7 @@ impl<'a> FormatWrite<'a> for AstNode<'a, IfStatement<'a>> { "if", space(), "(", - group(&soft_block_indent(&format_args!( - FormatTestOfIfAndWhileStatement(test), - FormatCommentForEmptyStatement(consequent) - ))), + group(&soft_block_indent(&FormatTestOfIfAndWhileStatement(test))), ")", FormatStatementBody::new(consequent), )) @@ -780,38 +777,36 @@ impl<'a> FormatWrite<'a> for AstNode<'a, IfStatement<'a>> { let alternate_start = alternate.span().start; let comments = f.context().comments().comments_before(alternate_start); - let has_line_comment = comments.iter().any(|comment| comment.kind == CommentKind::Line); - let has_dangling_comments = has_line_comment - || comments.last().is_some_and(|last_comment| { + let has_line_comment = comments.iter().any(|comment| comment.is_line()); + let has_dangling_comments = comments + .last() + .or(f.comments().printed_comments().last()) + .is_some_and(|last_comment| { // Ensure the comments are placed before the else keyword or on a new line - f.source_text() - .slice_range(last_comment.span.end, alternate_start) - .contains("else") - || f.source_text() - .contains_newline_between(last_comment.span.end, alternate_start) + f.source_text().slice_range(last_comment.span.end, alternate_start).trim() + == "else" }); - let else_on_same_line = - matches!(consequent.as_ref(), Statement::BlockStatement(_)) && !has_line_comment; + let else_on_same_line = matches!(consequent.as_ref(), Statement::BlockStatement(_)) + && (!has_line_comment || !has_dangling_comments); if else_on_same_line { - write!(f, space()); + write!(f, [space(), has_dangling_comments.then(line_suffix_boundary)]); } else { write!(f, hard_line_break()); } - if has_dangling_comments { + if has_dangling_comments && let Some(first_comment) = comments.first() { + if f.source_text().get_lines_before(first_comment.span, f.comments()) > 1 { + write!(f, empty_line()); + } + write!( + f, + FormatDanglingComments::Comments { comments, indent: DanglingIndentMode::None } + ); if has_line_comment { - write!(f, FormatTrailingComments::Comments(comments)); write!(f, hard_line_break()); } else { - write!( - f, - FormatDanglingComments::Comments { - comments, - indent: DanglingIndentMode::None - } - ); write!(f, space()); } } @@ -820,6 +815,7 @@ impl<'a> FormatWrite<'a> for AstNode<'a, IfStatement<'a>> { f, [ "else", + line_suffix_boundary(), group(&FormatStatementBody::new(alternate).with_forced_space(matches!( alternate.as_ref(), Statement::IfStatement(_) diff --git a/crates/oxc_formatter/tests/fixtures/js/if/issue-16137.js b/crates/oxc_formatter/tests/fixtures/js/if/issue-16137.js new file mode 100644 index 0000000000000..28912b3dbd8e4 --- /dev/null +++ b/crates/oxc_formatter/tests/fixtures/js/if/issue-16137.js @@ -0,0 +1,10 @@ +if (x) { + // test +} //test +else if (x) { + // test +} + +if (cond) stuff; +/* comment*/ +else stuff; diff --git a/crates/oxc_formatter/tests/fixtures/js/if/issue-16137.js.snap b/crates/oxc_formatter/tests/fixtures/js/if/issue-16137.js.snap new file mode 100644 index 0000000000000..a25b09b1ca3e4 --- /dev/null +++ b/crates/oxc_formatter/tests/fixtures/js/if/issue-16137.js.snap @@ -0,0 +1,43 @@ +--- +source: crates/oxc_formatter/tests/fixtures/mod.rs +--- +==================== Input ==================== +if (x) { + // test +} //test +else if (x) { + // test +} + +if (cond) stuff; +/* comment*/ +else stuff; + +==================== Output ==================== +------------------ +{ printWidth: 80 } +------------------ +if (x) { + // test +} //test +else if (x) { + // test +} + +if (cond) stuff; +/* comment*/ else stuff; + +------------------- +{ printWidth: 100 } +------------------- +if (x) { + // test +} //test +else if (x) { + // test +} + +if (cond) stuff; +/* comment*/ else stuff; + +===================== End ===================== diff --git a/tasks/prettier_conformance/snapshots/prettier.js.snap.md b/tasks/prettier_conformance/snapshots/prettier.js.snap.md index 13f2faa5bdebf..9e94ac7936455 100644 --- a/tasks/prettier_conformance/snapshots/prettier.js.snap.md +++ b/tasks/prettier_conformance/snapshots/prettier.js.snap.md @@ -1,4 +1,4 @@ -js compatibility: 729/759 (96.05%) +js compatibility: 734/759 (96.71%) # Failed @@ -9,7 +9,6 @@ js compatibility: 729/759 (96.05%) | js/comments/dangling_for.js | 💥💥 | 22.22% | | js/comments/empty-statements.js | 💥💥 | 90.91% | | js/comments/function-declaration.js | 💥💥 | 92.80% | -| js/comments/if.js | 💥💥 | 74.83% | | js/comments/return-statement.js | 💥💥 | 98.28% | | js/explicit-resource-management/for-await-using-of-comments.js | 💥 | 0.00% | | js/explicit-resource-management/valid-await-using-comments.js | 💥 | 68.57% | @@ -19,10 +18,6 @@ js compatibility: 729/759 (96.05%) | js/for/parentheses.js | 💥 | 97.96% | | js/identifier/for-of/let.js | 💥 | 92.31% | | js/identifier/parentheses/let.js | 💥💥 | 82.27% | -| js/if/comment-between-condition-and-body.js | 💥 | 65.79% | -| js/if/expr_and_same_line_comments.js | 💥 | 97.73% | -| js/if/if_comments.js | 💥 | 76.00% | -| js/if/trailing_comment.js | 💥 | 91.43% | | js/last-argument-expansion/dangling-comment-in-arrow-function.js | 💥 | 22.22% | | js/object-multiline/multiline.js | 💥✨ | 22.22% | | js/quotes/objects.js | 💥💥 | 80.00% |