Skip to content

Commit d4a12e7

Browse files
committed
feat: support Deno.test calls with a parameter being considered a test call expr.
1 parent 0e7f305 commit d4a12e7

File tree

3 files changed

+112
-50
lines changed

3 files changed

+112
-50
lines changed

src/parsing/node_helpers.rs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ pub fn get_leading_comment_on_different_line<'a>(node: &dyn Spanned, comments_to
5858
None
5959
}
6060

61+
pub fn has_surrounding_comments(node: &Node, module: &Module) -> bool {
62+
!node.leading_comments_fast(module).is_empty() || !node.trailing_comments_fast(module).is_empty()
63+
}
64+
6165
pub fn nodes_have_only_spaces_between(previous_node: &Node, next_node: &Node, module: &Module) -> bool {
6266
if let Node::JSXText(previous_node) = previous_node {
6367
let previous_node_text = previous_node.text_fast(module);
@@ -142,8 +146,25 @@ pub fn is_test_library_call_expr(node: &CallExpr, module: &Module) -> bool {
142146
if node.args[0].expr.kind() != NodeKind::Str && !node.args[0].expr.is::<Tpl>() {
143147
return false;
144148
}
145-
if node.args[1].expr.kind() != NodeKind::FnExpr && node.args[1].expr.kind() != NodeKind::ArrowExpr {
146-
return false;
149+
150+
match node.args[1].expr {
151+
Expr::Fn(fn_expr) => {
152+
if !fn_expr.function.params.is_empty() {
153+
return false;
154+
}
155+
}
156+
Expr::Arrow(arrow_expr) => {
157+
if arrow_expr.params.len() > 1 {
158+
return false;
159+
}
160+
// allow something like `Deno.test("desc", (t) => {})`
161+
if let Some(param) = arrow_expr.params.get(0) {
162+
if has_surrounding_comments(&param.into(), module) {
163+
return false;
164+
}
165+
}
166+
}
167+
_ => return false,
147168
}
148169

149170
return node.start_line_fast(module) == node.args[1].start_line_fast(module);

src/parsing/parser.rs

Lines changed: 60 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1431,51 +1431,67 @@ fn parse_arrow_func_expr<'a>(node: &'a ArrowExpr, context: &mut Context<'a>) ->
14311431
};
14321432

14331433
fn parse_inner<'a>(node: &'a ArrowExpr, context: &mut Context<'a>) -> PrintItems {
1434-
let mut items = PrintItems::new();
14351434
let header_start_info = Info::new("arrowFunctionExpressionHeaderStart");
1436-
let should_use_parens = get_should_use_parens(&node, context);
1437-
1438-
items.push_info(header_start_info);
1439-
if node.is_async() {
1440-
items.push_str("async ");
1441-
}
1442-
if let Some(type_params) = node.type_params {
1443-
items.extend(parse_node(type_params.into(), context));
1444-
}
1445-
1446-
if should_use_parens {
1447-
// need to check if there are parens because parse_parameters_or_arguments depends on the parens existing
1448-
if has_parens(node, context) {
1449-
items.extend(parse_parameters_or_arguments(
1450-
ParseParametersOrArgumentsOptions {
1451-
node: node.into(),
1452-
span: node.get_parameters_span(context),
1453-
nodes: node.params.iter().map(|node| node.into()).collect(),
1454-
custom_close_paren: |context| {
1455-
Some(parse_close_paren_with_type(
1456-
ParseCloseParenWithTypeOptions {
1457-
start_info: header_start_info,
1458-
type_node: node.return_type.map(|x| x.into()),
1459-
type_node_separator: None,
1460-
param_count: node.params.len(),
1461-
},
1462-
context,
1463-
))
1435+
let header_items = {
1436+
let mut items = PrintItems::new();
1437+
let should_use_parens = get_should_use_parens(&node, context);
1438+
1439+
items.push_info(header_start_info);
1440+
if node.is_async() {
1441+
items.push_str("async ");
1442+
}
1443+
if let Some(type_params) = node.type_params {
1444+
items.extend(parse_node(type_params.into(), context));
1445+
}
1446+
1447+
if should_use_parens {
1448+
// need to check if there are parens because parse_parameters_or_arguments depends on the parens existing
1449+
if has_parens(node, context) {
1450+
items.extend(parse_parameters_or_arguments(
1451+
ParseParametersOrArgumentsOptions {
1452+
node: node.into(),
1453+
span: node.get_parameters_span(context),
1454+
nodes: node.params.iter().map(|node| node.into()).collect(),
1455+
custom_close_paren: |context| {
1456+
Some(parse_close_paren_with_type(
1457+
ParseCloseParenWithTypeOptions {
1458+
start_info: header_start_info,
1459+
type_node: node.return_type.map(|x| x.into()),
1460+
type_node_separator: None,
1461+
param_count: node.params.len(),
1462+
},
1463+
context,
1464+
))
1465+
},
1466+
is_parameters: true,
14641467
},
1465-
is_parameters: true,
1466-
},
1467-
context,
1468-
));
1468+
context,
1469+
));
1470+
} else {
1471+
// todo: this should probably use more of the same logic as in parse_parameters_or_arguments
1472+
// there will only be one param in this case
1473+
items.extend(surround_with_parens(parse_node(node.params.first().unwrap().into(), context)));
1474+
}
14691475
} else {
1470-
// todo: this should probably use more of the same logic as in parse_parameters_or_arguments
1471-
// there will only be one param in this case
1472-
items.extend(surround_with_parens(parse_node(node.params.first().unwrap().into(), context)));
1476+
items.extend(parse_node(node.params.first().unwrap().into(), context));
14731477
}
1474-
} else {
1475-
items.extend(parse_node(node.params.first().unwrap().into(), context));
1476-
}
14771478

1478-
items.push_str(" =>");
1479+
items.push_str(" =>");
1480+
items
1481+
};
1482+
1483+
let is_arrow_in_test_call_expr = node
1484+
.parent()
1485+
.parent()
1486+
.unwrap()
1487+
.to::<CallExpr>()
1488+
.map(|c| node_helpers::is_test_library_call_expr(c, context.module))
1489+
.unwrap_or(false);
1490+
let mut items = if is_arrow_in_test_call_expr {
1491+
parser_helpers::with_no_new_lines(header_items)
1492+
} else {
1493+
header_items
1494+
};
14791495

14801496
let parsed_body = parse_node(node.body.into(), context);
14811497
let parsed_body = if use_new_line_group_for_arrow_body(node, context) {
@@ -2367,7 +2383,7 @@ fn parse_paren_expr<'a>(node: &'a ParenExpr, context: &mut Context<'a>) -> Print
23672383
}
23682384

23692385
fn should_skip_paren_expr(node: &ParenExpr, context: &Context) -> bool {
2370-
if has_surrounding_comments(&node.expr.into(), context) {
2386+
if node_helpers::has_surrounding_comments(&node.expr.into(), context.module) {
23712387
return false;
23722388
}
23732389

@@ -3066,7 +3082,7 @@ fn handle_jsx_surrounding_parens<'a>(inner_items: PrintItems, context: &mut Cont
30663082
fn should_jsx_surround_newlines(node: &Node, context: &Context) -> bool {
30673083
let mut parent = node.parent().unwrap();
30683084
while let Some(paren_expr) = parent.to::<ParenExpr>() {
3069-
if has_surrounding_comments(&paren_expr.expr.into(), context) {
3085+
if node_helpers::has_surrounding_comments(&paren_expr.expr.into(), context.module) {
30703086
return false;
30713087
}
30723088
parent = parent.parent().unwrap();
@@ -3085,13 +3101,13 @@ fn is_jsx_paren_expr_handled_node(node: &Node, context: &Context) -> bool {
30853101
return false;
30863102
}
30873103

3088-
if has_surrounding_comments(node, context) {
3104+
if node_helpers::has_surrounding_comments(node, context.module) {
30893105
return false;
30903106
}
30913107

30923108
let mut parent = node.parent().unwrap();
30933109
while parent.is::<ParenExpr>() {
3094-
if has_surrounding_comments(&parent, context) {
3110+
if node_helpers::has_surrounding_comments(&parent, context.module) {
30953111
return false;
30963112
}
30973113
parent = parent.parent().unwrap();
@@ -3104,10 +3120,6 @@ fn is_jsx_paren_expr_handled_node(node: &Node, context: &Context) -> bool {
31043120
)
31053121
}
31063122

3107-
fn has_surrounding_comments(node: &Node, context: &Context) -> bool {
3108-
!node.leading_comments_fast(context.module).is_empty() || !node.trailing_comments_fast(context.module).is_empty()
3109-
}
3110-
31113123
fn parse_jsx_element<'a>(node: &'a JSXElement, context: &mut Context<'a>) -> PrintItems {
31123124
let items = if let Some(closing) = node.closing {
31133125
let result = parse_jsx_with_opening_and_closing(

tests/specs/expressions/CallExpression/CallExpression_TestLibraries.txt

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,32 @@ Deno.test("testing this out with a long string", () => {
7070
Deno.test("testing this out with a long string", () => {
7171
// etc...
7272
});
73+
74+
== should not go multiline for `Deno.test` call with parameter ==
75+
Deno.test("testing this out testing testing testing testing", async (t) => {
76+
// etc...
77+
});
78+
Deno.test("testing this out testing testing testing testing", (t) => {
79+
// etc...
80+
});
81+
82+
[expect]
83+
Deno.test("testing this out testing testing testing testing", async (t) => {
84+
// etc...
85+
});
86+
Deno.test("testing this out testing testing testing testing", (t) => {
87+
// etc...
88+
});
89+
90+
== should go multi-line if the parameter has a comment inside ==
91+
Deno.test("testing this out testing testing testing testing", (/*1*/t) => {
92+
// etc...
93+
});
94+
95+
[expect]
96+
Deno.test(
97+
"testing this out testing testing testing testing",
98+
(/*1*/ t) => {
99+
// etc...
100+
},
101+
);

0 commit comments

Comments
 (0)