From 4994872c6253f05b2e9071f60153e3f83b0eed0f Mon Sep 17 00:00:00 2001 From: Dunqing <29533304+Dunqing@users.noreply.github.com> Date: Sun, 12 Oct 2025 16:13:23 +0000 Subject: [PATCH] fix(formatter): correct printing comments for `try` statement (#14497) --- .../oxc_formatter/src/write/try_statement.rs | 35 +++++++++++++------ tasks/coverage/snapshots/formatter_babel.snap | 4 +-- .../snapshots/formatter_typescript.snap | 4 +-- 3 files changed, 27 insertions(+), 16 deletions(-) diff --git a/crates/oxc_formatter/src/write/try_statement.rs b/crates/oxc_formatter/src/write/try_statement.rs index 61c18ec1f4e28..d693ce646fbf9 100644 --- a/crates/oxc_formatter/src/write/try_statement.rs +++ b/crates/oxc_formatter/src/write/try_statement.rs @@ -9,7 +9,10 @@ use crate::{ Formatter, prelude::*, separated::FormatSeparatedIter, - trivia::{FormatLeadingComments, FormatTrailingComments}, + trivia::{ + DanglingIndentMode, FormatDanglingComments, FormatLeadingComments, + FormatTrailingComments, + }, }, generated::ast_nodes::{AstNode, AstNodes}, write, @@ -40,15 +43,27 @@ impl<'a> FormatWrite<'a> for AstNode<'a, TryStatement<'a>> { impl<'a> FormatWrite<'a> for AstNode<'a, CatchClause<'a>> { fn write(&self, f: &mut Formatter<'_, 'a>) -> FormatResult<()> { - // `try {} /* comment */ catch (e) {}` - // should be formatted like: - // `try {} catch (e) { /* comment */ }` - // - // Comments before the catch clause should be printed in the block statement. - // We cache them here to avoid the `params` printing them accidentally. - let printed_comments = f.intern(&format_leading_comments(self.span)); - if let Ok(Some(comments)) = printed_comments { - f.context_mut().cache_element(&self.span, comments); + let comments = f.context().comments().comments_before(self.span.start); + let has_line_comment = comments.iter().any(|comment| { + comment.is_line() + || f.source_text().is_own_line_comment(comment) + || f.source_text().is_end_of_line_comment(comment) + }); + + if has_line_comment { + // `try {} /* comment */\n catch (e) {}` + // should be formatted like: + // `try {} catch (e) { /* comment */ }` + // + // Comments before the catch clause should be printed in the block statement. + // We cache them here to avoid the `params` printing them accidentally. + let printed_comments = f.intern(&FormatLeadingComments::Comments(comments)); + if let Ok(Some(comments)) = printed_comments { + f.context_mut().cache_element(&self.span, comments); + } + } else if !comments.is_empty() { + // otherwise, print them before `catch` + write!(f, [FormatTrailingComments::Comments(comments), space()]); } write!(f, ["catch", space(), self.param(), space()])?; diff --git a/tasks/coverage/snapshots/formatter_babel.snap b/tasks/coverage/snapshots/formatter_babel.snap index d848b5c7f66a6..1b4780425c738 100644 --- a/tasks/coverage/snapshots/formatter_babel.snap +++ b/tasks/coverage/snapshots/formatter_babel.snap @@ -2,8 +2,6 @@ commit: 41d96516 formatter_babel Summary: AST Parsed : 2423/2423 (100.00%) -Positive Passed: 2421/2423 (99.92%) -Mismatch: tasks/coverage/babel/packages/babel-parser/test/fixtures/comments/basic/try-statement/input.js - +Positive Passed: 2422/2423 (99.96%) Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/es2022/top-level-await-unambiguous/module/input.js `await` is only allowed within async functions and at the top levels of modules diff --git a/tasks/coverage/snapshots/formatter_typescript.snap b/tasks/coverage/snapshots/formatter_typescript.snap index 840bd54724807..ed8d64514b1ae 100644 --- a/tasks/coverage/snapshots/formatter_typescript.snap +++ b/tasks/coverage/snapshots/formatter_typescript.snap @@ -2,7 +2,7 @@ commit: 261630d6 formatter_typescript Summary: AST Parsed : 8816/8816 (100.00%) -Positive Passed: 8807/8816 (99.90%) +Positive Passed: 8808/8816 (99.91%) Mismatch: tasks/coverage/typescript/tests/cases/compiler/amdLikeInputDeclarationEmit.ts Expect to Parse: tasks/coverage/typescript/tests/cases/compiler/arrayFromAsync.ts @@ -11,8 +11,6 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/compiler/genericTypeAsser Unexpected token Mismatch: tasks/coverage/typescript/tests/cases/compiler/propertyAccessExpressionInnerComments.ts -Mismatch: tasks/coverage/typescript/tests/cases/compiler/tryStatementInternalComments.ts - Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/classes/propertyMemberDeclarations/staticPropertyNameConflicts.ts Classes may not have a static property named prototypeClasses may not have a static property named prototypeClasses may not have a static property named prototypeClasses may not have a static property named prototypeClasses may not have a static property named prototypeClasses may not have a static property named prototype Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/expressions/elementAccess/letIdentifierInElementAccess01.ts