Skip to content

Commit 5948ab7

Browse files
committed
feat(formatter): correct printing parameters with return_type for function-like node
1 parent 47e0819 commit 5948ab7

File tree

11 files changed

+154
-147
lines changed

11 files changed

+154
-147
lines changed

crates/oxc_formatter/src/generated/format.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4610,9 +4610,19 @@ impl<'a> Format<'a> for AstNode<'a, TSImportTypeQualifiedName<'a>> {
46104610
impl<'a> Format<'a> for AstNode<'a, TSFunctionType<'a>> {
46114611
fn fmt(&self, f: &mut Formatter<'_, 'a>) -> FormatResult<()> {
46124612
let is_suppressed = f.comments().is_suppressed(self.span().start);
4613+
if !is_suppressed && format_type_cast_comment_node(self, false, f)? {
4614+
return Ok(());
4615+
}
46134616
self.format_leading_comments(f)?;
4617+
let needs_parentheses = self.needs_parentheses(f);
4618+
if needs_parentheses {
4619+
"(".fmt(f)?;
4620+
}
46144621
let result =
46154622
if is_suppressed { FormatSuppressedNode(self.span()).fmt(f) } else { self.write(f) };
4623+
if needs_parentheses {
4624+
")".fmt(f)?;
4625+
}
46164626
self.format_trailing_comments(f)?;
46174627
result
46184628
}

crates/oxc_formatter/src/write/class.rs

Lines changed: 60 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ use crate::{
2020
object::format_property_key,
2121
},
2222
write,
23-
write::{semicolon::OptionalSemicolon, type_parameters},
23+
write::{
24+
function::should_group_function_parameters, semicolon::OptionalSemicolon, type_parameters,
25+
},
2426
};
2527

2628
use super::{
@@ -83,6 +85,7 @@ impl<'a> FormatWrite<'a> for AstNode<'a, MethodDefinition<'a>> {
8385
}
8486
}
8587
let value = self.value();
88+
8689
if value.r#async {
8790
write!(f, ["async", space()])?;
8891
}
@@ -95,22 +98,27 @@ impl<'a> FormatWrite<'a> for AstNode<'a, MethodDefinition<'a>> {
9598
format_property_key(self.key(), f)?;
9699
}
97100

98-
if self.optional() {
101+
if self.optional {
99102
write!(f, "?")?;
100103
}
101-
if let Some(type_parameters) = &value.type_parameters() {
102-
write!(f, type_parameters)?;
103-
}
104-
// Handle comments between method name and parameters
105-
// Example: method /* comment */ (param) {}
106-
let comments = f.context().comments().comments_before(value.params().span.start);
107-
if !comments.is_empty() {
108-
write!(f, [space(), FormatTrailingComments::Comments(comments)])?;
109-
}
110-
write!(f, group(&value.params()))?;
111-
if let Some(return_type) = &value.return_type() {
112-
write!(f, return_type)?;
104+
105+
if value.type_parameters.is_none() {
106+
// // Handle comments between method name and parameters
107+
// // Example: method /* comment */ (param) {}
108+
// let comments = f.context().comments().comments_before(value.params().span.start);
109+
// if !comments.is_empty() {
110+
// write!(f, [space(), FormatTrailingComments::Comments(comments)])?;
111+
// }
113112
}
113+
114+
format_grouped_parameters_with_return_type(
115+
value.type_parameters(),
116+
value.this_param.as_deref(),
117+
value.params(),
118+
value.return_type(),
119+
f,
120+
)?;
121+
114122
if let Some(body) = &value.body() {
115123
// Handle block comments between method signature and body
116124
// Example: method() /* comment */ {}
@@ -623,3 +631,41 @@ impl<'a> Format<'a> for ClassPropertySemicolon<'a, '_> {
623631
}
624632
}
625633
}
634+
635+
pub fn format_grouped_parameters_with_return_type<'a>(
636+
type_parameters: Option<&AstNode<'a, TSTypeParameterDeclaration<'a>>>,
637+
this_param: Option<&TSThisParameter<'a>>,
638+
params: &AstNode<'a, FormalParameters<'a>>,
639+
return_type: Option<&AstNode<'a, TSTypeAnnotation<'a>>>,
640+
f: &mut Formatter<'_, 'a>,
641+
) -> FormatResult<()> {
642+
write!(f, [type_parameters])?;
643+
644+
group(&format_once(|f| {
645+
let mut format_parameters = params.memoized();
646+
let mut format_return_type = return_type.memoized();
647+
648+
// Inspect early, in case the `return_type` is formatted before `parameters`
649+
// in `should_group_function_parameters`.
650+
format_parameters.inspect(f)?;
651+
652+
let group_parameters = should_group_function_parameters(
653+
type_parameters.map(AsRef::as_ref),
654+
params.items.len()
655+
+ usize::from(params.rest.is_some())
656+
+ usize::from(this_param.is_some()),
657+
return_type.map(AsRef::as_ref),
658+
&mut format_return_type,
659+
f,
660+
)?;
661+
662+
if group_parameters {
663+
write!(f, [group(&format_parameters)])
664+
} else {
665+
write!(f, [format_parameters])
666+
}?;
667+
668+
write!(f, [format_return_type])
669+
}))
670+
.fmt(f)
671+
}

crates/oxc_formatter/src/write/function.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,10 +117,10 @@ impl<'a> FormatWrite<'a> for FormatFunction<'a, '_> {
117117
)?;
118118

119119
if group_parameters {
120-
write!(f, [group(&format_parameters)])?;
120+
write!(f, [group(&format_parameters)])
121121
} else {
122-
write!(f, [format_parameters])?;
123-
}
122+
write!(f, [format_parameters])
123+
}?;
124124

125125
write!(f, [format_return_type])
126126
}))]

crates/oxc_formatter/src/write/mod.rs

Lines changed: 49 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ use crate::{
7878

7979
use self::{
8080
array_expression::FormatArrayExpression,
81+
class::format_grouped_parameters_with_return_type,
82+
function::should_group_function_parameters,
8183
object_like::ObjectLike,
8284
object_pattern_like::ObjectPatternLike,
8385
parameters::{ParameterLayout, ParameterList},
@@ -1072,10 +1074,16 @@ impl<'a> FormatWrite<'a> for AstNode<'a, TSEnumMember<'a>> {
10721074

10731075
impl<'a> FormatWrite<'a> for AstNode<'a, TSTypeAnnotation<'a>> {
10741076
fn write(&self, f: &mut Formatter<'_, 'a>) -> FormatResult<()> {
1075-
if matches!(self.parent, AstNodes::TSTypePredicate(_)) {
1076-
write!(f, [self.type_annotation()])
1077-
} else {
1078-
write!(f, [":", space(), self.type_annotation()])
1077+
match self.parent {
1078+
AstNodes::TSFunctionType(_) | AstNodes::TSConstructorType(_) => {
1079+
write!(f, ["=>", space(), self.type_annotation()])
1080+
}
1081+
AstNodes::TSTypePredicate(_) => {
1082+
write!(f, [self.type_annotation()])
1083+
}
1084+
_ => {
1085+
write!(f, [":", space(), self.type_annotation()])
1086+
}
10791087
}
10801088
}
10811089
}
@@ -1466,18 +1474,7 @@ impl<'a> Format<'a> for AstNode<'a, Vec<'a, TSSignature<'a>>> {
14661474

14671475
impl<'a> FormatWrite<'a> for AstNode<'a, TSCallSignatureDeclaration<'a>> {
14681476
fn write(&self, f: &mut Formatter<'_, 'a>) -> FormatResult<()> {
1469-
if let Some(type_parameters) = &self.type_parameters() {
1470-
write!(f, group(type_parameters))?;
1471-
}
1472-
1473-
if let Some(this_param) = &self.this_param() {
1474-
write!(f, [this_param, ",", soft_line_break_or_space()])?;
1475-
}
1476-
write!(f, group(&self.params()))?;
1477-
if let Some(return_type) = &self.return_type() {
1478-
write!(f, return_type)?;
1479-
}
1480-
Ok(())
1477+
write!(f, group(&format_args!(self.type_parameters(), self.params(), self.return_type())))
14811478
}
14821479
}
14831480

@@ -1502,42 +1499,21 @@ impl<'a> FormatWrite<'a> for AstNode<'a, TSMethodSignature<'a>> {
15021499
if self.optional() {
15031500
write!(f, "?")?;
15041501
}
1505-
// TODO:
1506-
// if should_group_function_parameters(
1507-
// type_parameters.as_ref(),
1508-
// parameters.len(),
1509-
// return_type_annotation
1510-
// .as_ref()
1511-
// .map(|annotation| annotation.ty()),
1512-
// &mut format_return_type_annotation,
1513-
// f,
1514-
// )? {
1515-
// write!(f, [group(&parameters)])?;
1516-
// } else {
1517-
// write!(f, [parameters])?;
1518-
// }
1519-
if let Some(type_parameters) = &self.type_parameters() {
1520-
write!(f, [group(&type_parameters)])?;
1521-
}
1522-
write!(f, group(&self.params()))?;
1523-
if let Some(return_type) = &self.return_type() {
1524-
write!(f, return_type)?;
1525-
}
1526-
Ok(())
1502+
1503+
format_grouped_parameters_with_return_type(
1504+
self.type_parameters(),
1505+
self.this_param.as_deref(),
1506+
self.params(),
1507+
self.return_type(),
1508+
f,
1509+
)
15271510
}
15281511
}
15291512

15301513
impl<'a> FormatWrite<'a> for AstNode<'a, TSConstructSignatureDeclaration<'a>> {
15311514
fn write(&self, f: &mut Formatter<'_, 'a>) -> FormatResult<()> {
15321515
write!(f, ["new", space()])?;
1533-
if let Some(type_parameters) = &self.type_parameters() {
1534-
write!(f, group(&type_parameters))?;
1535-
}
1536-
write!(f, group(&self.params()))?;
1537-
if let Some(return_type) = self.return_type() {
1538-
write!(f, return_type)?;
1539-
}
1540-
Ok(())
1516+
write!(f, group(&format_args!(self.type_parameters(), self.params(), self.return_type())))
15411517
}
15421518
}
15431519

@@ -1677,45 +1653,39 @@ impl<'a> FormatWrite<'a> for AstNode<'a, TSImportTypeQualifiedName<'a>> {
16771653

16781654
impl<'a> FormatWrite<'a> for AstNode<'a, TSFunctionType<'a>> {
16791655
fn write(&self, f: &mut Formatter<'_, 'a>) -> FormatResult<()> {
1680-
let type_parameters = self.type_parameters();
1681-
let params = self.params();
1682-
let return_type = self.return_type();
1683-
16841656
let format_inner = format_with(|f| {
1657+
let type_parameters = self.type_parameters();
16851658
write!(f, type_parameters)?;
16861659

1687-
// TODO
1688-
// let mut format_return_type = return_type.format().memoized();
1689-
let should_group_parameters = false;
1690-
// TODO
1691-
//should_group_function_parameters(
1692-
// type_parameters.as_ref(),
1693-
// parameters.as_ref()?.items().len(),
1694-
// Some(return_type.clone()),
1695-
// &mut format_return_type,
1696-
// f,
1697-
// )?;
1698-
1699-
if should_group_parameters {
1700-
write!(f, group(&params))?;
1701-
} else {
1702-
write!(f, params)?;
1703-
}
1660+
let params = self.params();
1661+
let return_type = self.return_type();
1662+
let mut format_parameters = params.memoized();
1663+
let mut format_return_type = return_type.memoized();
1664+
1665+
// Inspect early, in case the `return_type` is formatted before `parameters`
1666+
// in `should_group_function_parameters`.
1667+
format_parameters.inspect(f)?;
1668+
1669+
let group_parameters = should_group_function_parameters(
1670+
type_parameters.map(AsRef::as_ref),
1671+
params.items.len()
1672+
+ usize::from(params.rest.is_some())
1673+
+ usize::from(self.this_param.is_some()),
1674+
Some(&self.return_type),
1675+
&mut format_return_type,
1676+
f,
1677+
)?;
17041678

1705-
let comments = f.context().comments().comments_before_character(params.span.end, b'=');
1706-
FormatTrailingComments::Comments(comments).fmt(f)?;
1679+
if group_parameters {
1680+
write!(f, [group(&format_parameters)])
1681+
} else {
1682+
write!(f, [format_parameters])
1683+
}?;
17071684

1708-
write!(f, [space(), "=>", space(), return_type.type_annotation()])
1685+
write!(f, [space(), format_return_type])
17091686
});
17101687

1711-
if self.needs_parentheses(f) {
1712-
"(".fmt(f)?;
1713-
}
1714-
write!(f, group(&format_inner))?;
1715-
if self.needs_parentheses(f) {
1716-
")".fmt(f)?;
1717-
}
1718-
Ok(())
1688+
write!(f, group(&format_inner))
17191689
}
17201690
}
17211691

@@ -1731,21 +1701,7 @@ impl<'a> FormatWrite<'a> for AstNode<'a, TSConstructorType<'a>> {
17311701
}
17321702
write!(
17331703
f,
1734-
[group(&format_args!(
1735-
"new",
1736-
space(),
1737-
type_parameters,
1738-
params,
1739-
format_once(|f| {
1740-
let comments =
1741-
f.context().comments().comments_before_character(params.span.end, b'=');
1742-
FormatTrailingComments::Comments(comments).fmt(f)
1743-
}),
1744-
space(),
1745-
"=>",
1746-
space(),
1747-
return_type.type_annotation()
1748-
))]
1704+
[group(&format_args!("new", space(), type_parameters, params, space(), return_type))]
17491705
);
17501706
Ok(())
17511707
}

crates/oxc_formatter/src/write/object_like.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use crate::{
1010
generated::ast_nodes::{AstNode, AstNodes},
1111
options::Expand,
1212
write,
13-
write::parameters::should_hug_function_parameters,
13+
write::parameters::{get_this_param, should_hug_function_parameters},
1414
};
1515

1616
#[derive(Clone, Copy)]
@@ -39,11 +39,7 @@ impl<'a> ObjectLike<'a, '_> {
3939
let AstNodes::FormalParameters(parameters) = &param.parent else {
4040
unreachable!()
4141
};
42-
let this_param = if let AstNodes::Function(function) = parameters.parent {
43-
function.this_param()
44-
} else {
45-
None
46-
};
42+
let this_param = get_this_param(parameters.parent);
4743
should_hug_function_parameters(parameters, this_param, false, f)
4844

4945
}

crates/oxc_formatter/src/write/object_pattern_like.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use crate::{
99
},
1010
generated::ast_nodes::{AstNode, AstNodes},
1111
write,
12-
write::parameters::should_hug_function_parameters,
12+
write::parameters::{get_this_param, should_hug_function_parameters},
1313
};
1414

1515
use super::{
@@ -117,11 +117,7 @@ impl<'a> ObjectPatternLike<'a, '_> {
117117
matches!(self, Self::ObjectPattern(node) if {
118118
matches!(node.parent, AstNodes::FormalParameter(param) if {
119119
matches!(param.parent, AstNodes::FormalParameters(params) if {
120-
let this_param = if let AstNodes::Function(function) = params.parent {
121-
function.this_param()
122-
} else {
123-
None
124-
};
120+
let this_param = get_this_param(param.parent);
125121
should_hug_function_parameters(params, this_param, false, f)
126122
})
127123
})

0 commit comments

Comments
 (0)