Skip to content

Commit 8a0ff32

Browse files
authored
fix: allow JSX generic trailing comma iff required (#316)
1 parent 05265d7 commit 8a0ff32

File tree

3 files changed

+24
-10
lines changed

3 files changed

+24
-10
lines changed

src/parsing/parser.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5301,13 +5301,18 @@ fn parse_type_parameters<'a>(node: TypeParamNode<'a>, context: &mut Context<'a>)
53015301
// trailing commas should be allowed in type parameters only—not arguments
53025302
if let Some(type_params) = node.parent().get_type_parameters() {
53035303
if type_params.lo() == node.lo() {
5304-
// Always use trailing commas for arrow function expressions in a JSX file
5305-
// if one exists as it may be used to assist with parsing ambiguity.
5304+
// Use trailing commas for function expressions in a JSX file
5305+
// if the absence of one would lead to a parsing ambiguity.
53065306
if context.is_jsx && (node.parent().kind() == NodeKind::ArrowExpr || node.parent().parent().unwrap().kind() == NodeKind::FnExpr) {
5307-
let comma_count = type_params.tokens_fast(context.module).iter().filter(|t| t.token == Token::Comma).count();
5308-
let has_trailing_comma = comma_count >= type_params.params.len();
5309-
if has_trailing_comma {
5310-
return TrailingCommas::Always;
5307+
let children = type_params.children();
5308+
// It is not ambiguous if there are multiple type parameters.
5309+
if children.len() == 1 && children[0].kind() == NodeKind::TsTypeParam {
5310+
let type_param = children[0];
5311+
let children = type_param.children();
5312+
// We have a possible ambiguity iff this type parameter is just an identifier.
5313+
if children.len() == 1 && children[0].kind() == NodeKind::Ident {
5314+
return TrailingCommas::Always;
5315+
}
53115316
}
53125317
}
53135318
return trailing_commas;

tests/specs/general/Jsx_TrailingCommas.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ const Test3 = <div></div>;
1515
function test<T,>() {
1616
}
1717

18+
// generic constraints are not ambiguous either
19+
const Test4 = <P extends R<S, T>,>() => {};
20+
const Test5 = <P extends R<S, T>>() => {};
21+
1822
[expect]
1923
const Test1 = <T,>() => false;
2024
const Test2 = function<T,>() {};
@@ -23,3 +27,7 @@ const Test3 = <div></div>;
2327
// not for declarations though
2428
function test<T>() {
2529
}
30+
31+
// generic constraints are not ambiguous either
32+
const Test4 = <P extends R<S, T>>() => {};
33+
const Test5 = <P extends R<S, T>>() => {};

tests/specs/issues/issue0303.txt

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,24 @@
1+
-- test.tsx --
12
== should format with comments ==
2-
const t = <X>() => (
3+
const t = <X,>() => (
34
<>
45
{/* Comment 1 */}
56
{/* Comment 2 */}
67
{/* Comment 3 */}
78
</>
89
);
9-
const u = <X>() => {
10+
const u = <X,>() => {
1011
// Hello world
1112
};
1213

1314
[expect]
14-
const t = <X>() => (
15+
const t = <X,>() => (
1516
<>
1617
{/* Comment 1 */}
1718
{/* Comment 2 */}
1819
{/* Comment 3 */}
1920
</>
2021
);
21-
const u = <X>() => {
22+
const u = <X,>() => {
2223
// Hello world
2324
};

0 commit comments

Comments
 (0)