From 0ef11bb542a9063660e57ab75d6be1268c895602 Mon Sep 17 00:00:00 2001 From: Dunqing <29533304+Dunqing@users.noreply.github.com> Date: Fri, 6 Feb 2026 05:58:05 +0000 Subject: [PATCH] fix(formatter): add space before type annotation with leading comment (#19012) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary When a comment appears between a function parameter name and its type annotation, oxfmt was missing the space before the comment. **Before (wrong):** ```tsx function f(x/* a */ : number) {} ``` **After (correct, matches Prettier):** ```tsx function f(x /* a */ : number) {} ``` ## Fix Check if there are comments before the type annotation and add a space if so: ```rust if let Some(type_ann) = self.type_annotation() { if f.comments().has_comment_before(type_ann.span().start) { write!(f, space()); } write!(f, type_ann); } ``` Fixes #18970 ## Test plan - [x] Added test fixture with various comment + type annotation patterns - [x] Tests pass for both regular and optional parameters - [x] Clippy passes 🤖 Generated with [Claude Code](https://claude.ai/code) --- crates/oxc_formatter/src/print/parameters.rs | 8 ++- .../comment-after-param-name.ts | 15 +++++ .../comment-after-param-name.ts.snap | 60 +++++++++++++++++++ 3 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 crates/oxc_formatter/tests/fixtures/ts/function-parameters/comment-after-param-name.ts create mode 100644 crates/oxc_formatter/tests/fixtures/ts/function-parameters/comment-after-param-name.ts.snap diff --git a/crates/oxc_formatter/src/print/parameters.rs b/crates/oxc_formatter/src/print/parameters.rs index b523ed09acf11..7cc36a1fb9b25 100644 --- a/crates/oxc_formatter/src/print/parameters.rs +++ b/crates/oxc_formatter/src/print/parameters.rs @@ -114,7 +114,13 @@ impl<'a> FormatWrite<'a> for AstNode<'a, FormalParameter<'a>> { if self.optional { write!(f, "?"); } - write!(f, self.type_annotation()); + + if let Some(type_ann) = self.type_annotation() { + if f.comments().has_comment_before(type_ann.span().start) { + write!(f, space()); + } + write!(f, type_ann); + } }) .memoized(); diff --git a/crates/oxc_formatter/tests/fixtures/ts/function-parameters/comment-after-param-name.ts b/crates/oxc_formatter/tests/fixtures/ts/function-parameters/comment-after-param-name.ts new file mode 100644 index 0000000000000..c43f9c5e5feff --- /dev/null +++ b/crates/oxc_formatter/tests/fixtures/ts/function-parameters/comment-after-param-name.ts @@ -0,0 +1,15 @@ +// Issue #18970 - comment between parameter name and type annotation +function f(x /* a */ : number) {} + +// Additional test cases +function g(y /* comment */ : string, z /* another */ : boolean) {} + +// With different comment styles +function h(a /* inline */ : number) {} + +// Multiple parameters with comments +const arrow = (x /* c1 */ : number, y /* c2 */ : string) => {}; + +// Optional parameters with comments +function optional(x? /* comment */ : number) {} +function optionalMultiple(a? /* c1 */ : string, b? /* c2 */ : number) {} diff --git a/crates/oxc_formatter/tests/fixtures/ts/function-parameters/comment-after-param-name.ts.snap b/crates/oxc_formatter/tests/fixtures/ts/function-parameters/comment-after-param-name.ts.snap new file mode 100644 index 0000000000000..49b4466b45414 --- /dev/null +++ b/crates/oxc_formatter/tests/fixtures/ts/function-parameters/comment-after-param-name.ts.snap @@ -0,0 +1,60 @@ +--- +source: crates/oxc_formatter/tests/fixtures/mod.rs +--- +==================== Input ==================== +// Issue #18970 - comment between parameter name and type annotation +function f(x /* a */ : number) {} + +// Additional test cases +function g(y /* comment */ : string, z /* another */ : boolean) {} + +// With different comment styles +function h(a /* inline */ : number) {} + +// Multiple parameters with comments +const arrow = (x /* c1 */ : number, y /* c2 */ : string) => {}; + +// Optional parameters with comments +function optional(x? /* comment */ : number) {} +function optionalMultiple(a? /* c1 */ : string, b? /* c2 */ : number) {} + +==================== Output ==================== +------------------ +{ printWidth: 80 } +------------------ +// Issue #18970 - comment between parameter name and type annotation +function f(x /* a */ : number) {} + +// Additional test cases +function g(y /* comment */ : string, z /* another */ : boolean) {} + +// With different comment styles +function h(a /* inline */ : number) {} + +// Multiple parameters with comments +const arrow = (x /* c1 */ : number, y /* c2 */ : string) => {}; + +// Optional parameters with comments +function optional(x? /* comment */ : number) {} +function optionalMultiple(a? /* c1 */ : string, b? /* c2 */ : number) {} + +------------------- +{ printWidth: 100 } +------------------- +// Issue #18970 - comment between parameter name and type annotation +function f(x /* a */ : number) {} + +// Additional test cases +function g(y /* comment */ : string, z /* another */ : boolean) {} + +// With different comment styles +function h(a /* inline */ : number) {} + +// Multiple parameters with comments +const arrow = (x /* c1 */ : number, y /* c2 */ : string) => {}; + +// Optional parameters with comments +function optional(x? /* comment */ : number) {} +function optionalMultiple(a? /* c1 */ : string, b? /* c2 */ : number) {} + +===================== End =====================