diff --git a/crates/oxc_formatter/src/write/class.rs b/crates/oxc_formatter/src/write/class.rs index f443b15ef7b69..1d2640bf985b9 100644 --- a/crates/oxc_formatter/src/write/class.rs +++ b/crates/oxc_formatter/src/write/class.rs @@ -102,15 +102,6 @@ impl<'a> FormatWrite<'a> for AstNode<'a, MethodDefinition<'a>> { write!(f, "?")?; } - if value.type_parameters.is_none() { - // // Handle comments between method name and parameters - // // Example: method /* comment */ (param) {} - // let comments = f.context().comments().comments_before(value.params().span.start); - // if !comments.is_empty() { - // write!(f, [space(), FormatTrailingComments::Comments(comments)])?; - // } - } - format_grouped_parameters_with_return_type( value.type_parameters(), value.this_param.as_deref(), @@ -639,30 +630,28 @@ pub fn format_grouped_parameters_with_return_type<'a>( return_type: Option<&AstNode<'a, TSTypeAnnotation<'a>>>, f: &mut Formatter<'_, 'a>, ) -> FormatResult<()> { - write!(f, [type_parameters])?; - group(&format_once(|f| { + let mut format_type_parameters = type_parameters.memoized(); let mut format_parameters = params.memoized(); let mut format_return_type = return_type.memoized(); // Inspect early, in case the `return_type` is formatted before `parameters` // in `should_group_function_parameters`. + format_type_parameters.inspect(f)?; format_parameters.inspect(f)?; let group_parameters = should_group_function_parameters( type_parameters.map(AsRef::as_ref), - params.items.len() - + usize::from(params.rest.is_some()) - + usize::from(this_param.is_some()), + params.parameters_count() + usize::from(this_param.is_some()), return_type.map(AsRef::as_ref), &mut format_return_type, f, )?; if group_parameters { - write!(f, [group(&format_parameters)]) + write!(f, [group(&format_args!(format_type_parameters, format_parameters))]) } else { - write!(f, [format_parameters]) + write!(f, [format_type_parameters, format_parameters]) }?; write!(f, [format_return_type]) diff --git a/crates/oxc_formatter/src/write/function.rs b/crates/oxc_formatter/src/write/function.rs index ceafa4d85531c..94e02fc4a87f8 100644 --- a/crates/oxc_formatter/src/write/function.rs +++ b/crates/oxc_formatter/src/write/function.rs @@ -108,9 +108,7 @@ impl<'a> FormatWrite<'a> for FormatFunction<'a, '_> { let group_parameters = should_group_function_parameters( self.type_parameters.as_deref(), - params.items.len() - + usize::from(params.rest.is_some()) - + usize::from(self.this_param.is_some()), + params.parameters_count() + usize::from(self.this_param.is_some()), self.return_type.as_deref(), &mut format_return_type, f, diff --git a/crates/oxc_formatter/src/write/mod.rs b/crates/oxc_formatter/src/write/mod.rs index 57b904de2f70a..fe9f7b3a81307 100644 --- a/crates/oxc_formatter/src/write/mod.rs +++ b/crates/oxc_formatter/src/write/mod.rs @@ -173,16 +173,16 @@ impl<'a> FormatWrite<'a> for AstNode<'a, ObjectProperty<'a>> { }; if self.method || is_accessor { - let AstNodes::Function(func) = self.value().as_ast_nodes() else { + let AstNodes::Function(value) = self.value().as_ast_nodes() else { unreachable!( "The `value` always be a function node if `method` or `accessor` is true" ) }; - if func.r#async() { + if value.r#async() { write!(f, ["async", space()])?; } - if func.generator() { + if value.generator() { write!(f, "*")?; } if self.computed { @@ -191,14 +191,15 @@ impl<'a> FormatWrite<'a> for AstNode<'a, ObjectProperty<'a>> { format_property_key(self.key(), f)?; } - if let Some(type_parameters) = &func.type_parameters() { - write!(f, type_parameters)?; - } - write!(f, group(&func.params()))?; - if let Some(return_type) = &func.return_type() { - write!(f, return_type)?; - } - if let Some(body) = &func.body() { + format_grouped_parameters_with_return_type( + value.type_parameters(), + value.this_param.as_deref(), + value.params(), + value.return_type(), + f, + )?; + + if let Some(body) = &value.body() { write!(f, [space(), body])?; } @@ -1561,7 +1562,13 @@ impl<'a> Format<'a> for AstNode<'a, Vec<'a, TSSignature<'a>>> { impl<'a> FormatWrite<'a> for AstNode<'a, TSCallSignatureDeclaration<'a>> { fn write(&self, f: &mut Formatter<'_, 'a>) -> FormatResult<()> { - write!(f, group(&format_args!(self.type_parameters(), self.params(), self.return_type()))) + format_grouped_parameters_with_return_type( + self.type_parameters(), + None, + self.params(), + self.return_type(), + f, + ) } } @@ -1600,7 +1607,13 @@ impl<'a> FormatWrite<'a> for AstNode<'a, TSMethodSignature<'a>> { impl<'a> FormatWrite<'a> for AstNode<'a, TSConstructSignatureDeclaration<'a>> { fn write(&self, f: &mut Formatter<'_, 'a>) -> FormatResult<()> { write!(f, ["new", space()])?; - write!(f, group(&format_args!(self.type_parameters(), self.params(), self.return_type()))) + format_grouped_parameters_with_return_type( + self.type_parameters(), + None, + self.params(), + self.return_type(), + f, + ) } } diff --git a/crates/oxc_formatter/tests/fixtures/ts/method-signatures/grouped.ts b/crates/oxc_formatter/tests/fixtures/ts/method-signatures/grouped.ts new file mode 100644 index 0000000000000..d98eb66615314 --- /dev/null +++ b/crates/oxc_formatter/tests/fixtures/ts/method-signatures/grouped.ts @@ -0,0 +1,24 @@ + +type A = { + new(...args): T<{ + A + } + > +}; + + +type A1 = { + (...args): T<{ + A + } + > +}; + +type A2 = { + bar( + ...args + ): T<{ + A + }> +} + diff --git a/crates/oxc_formatter/tests/fixtures/ts/method-signatures/grouped.ts.snap b/crates/oxc_formatter/tests/fixtures/ts/method-signatures/grouped.ts.snap new file mode 100644 index 0000000000000..4194336bb782b --- /dev/null +++ b/crates/oxc_formatter/tests/fixtures/ts/method-signatures/grouped.ts.snap @@ -0,0 +1,49 @@ +--- +source: crates/oxc_formatter/tests/fixtures/mod.rs +--- +==================== Input ==================== + +type A = { + new(...args): T<{ + A + } + > +}; + + +type A1 = { + (...args): T<{ + A + } + > +}; + +type A2 = { + bar( + ...args + ): T<{ + A + }> +} + + +==================== Output ==================== +type A = { + new (...args): T<{ + A; + }>; +}; + +type A1 = { + (...args): T<{ + A; + }>; +}; + +type A2 = { + bar(...args): T<{ + A; + }>; +}; + +===================== End ===================== diff --git a/crates/oxc_formatter/tests/fixtures/ts/objects/methods.ts b/crates/oxc_formatter/tests/fixtures/ts/objects/methods.ts new file mode 100644 index 0000000000000..4c2a678c24a13 --- /dev/null +++ b/crates/oxc_formatter/tests/fixtures/ts/objects/methods.ts @@ -0,0 +1,6 @@ +const builder = { + build(environment: BuildEnvironment): Promise< + RollupOutput | RollupOutput[] + > { + }, +} diff --git a/crates/oxc_formatter/tests/fixtures/ts/objects/methods.ts.snap b/crates/oxc_formatter/tests/fixtures/ts/objects/methods.ts.snap new file mode 100644 index 0000000000000..5b00fabcf02f7 --- /dev/null +++ b/crates/oxc_formatter/tests/fixtures/ts/objects/methods.ts.snap @@ -0,0 +1,19 @@ +--- +source: crates/oxc_formatter/tests/fixtures/mod.rs +--- +==================== Input ==================== +const builder = { + build(environment: BuildEnvironment): Promise< + RollupOutput | RollupOutput[] + > { + }, +} + +==================== Output ==================== +const builder = { + build( + environment: BuildEnvironment, + ): Promise {}, +}; + +===================== End =====================