Skip to content

Commit aeebd5a

Browse files
committed
Parse list and list spread in JSX
fixes #1467
1 parent 102442d commit aeebd5a

7 files changed

Lines changed: 2918 additions & 2586 deletions

File tree

‎formatTest/typeCheckedTests/expected_output/jsx.re‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -553,3 +553,12 @@ let div = (~onClick, ~children, ()) => ();
553553
<div onClick=onClickHandler>
554554
<> "foobar" </>
555555
</div>;
556+
557+
/* https://github.com/facebook/reason/issues/1467 */
558+
<Foo> 1 2 </Foo>;
559+
560+
<Foo> 1 2 3 4 </Foo>;
561+
562+
<Foo> <> 1 2 3 4 </> </Foo>;
563+
564+
<Foo> <> 1 2 3 </> </Foo>;

‎formatTest/typeCheckedTests/input/jsx.re‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,3 +436,12 @@ let onClickHandler = () => ();
436436
let div = (~onClick, ~children, ()) => ();
437437

438438
<div onClick=onClickHandler> <> "foobar" </> </div>;
439+
440+
/* https://github.com/facebook/reason/issues/1467 */
441+
<Foo> ...[1, 2] </Foo>;
442+
443+
<Foo> [1, 2] [3,4] </Foo>;
444+
445+
<Foo> <> [1, 2] [3,4] </> </Foo>;
446+
447+
<Foo> <> ...[1, 2, 3] </> </Foo>;

‎formatTest/unit_tests/expected_output/jsx.re‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,3 +270,5 @@ let x = foo /></ bar;
270270
<div onClick=this##handleClick>
271271
<> foo bar </>
272272
</div>;
273+
274+
<Foo> 1 2 other </Foo>;

‎formatTest/unit_tests/input/jsx.re‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,3 +171,5 @@ let x = foo /></ bar;
171171
<div onClick=this##handleClick>
172172
<> foo(bar) </>
173173
</div>;
174+
175+
<Foo> ...[[1,2] , other] </Foo>;

‎src/reason-parser/reason_parser.messages.checked-in‎

Lines changed: 2836 additions & 2578 deletions
Large diffs are not rendered by default.

‎src/reason-parser/reason_parser.mly‎

Lines changed: 58 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1036,6 +1036,11 @@ let raise_record_trailing_semi_error loc =
10361036
let msg = "Record entries are separated by comma; we've found a semicolon instead." in
10371037
raise Reason_syntax_util.(Error(loc, (Syntax_error msg)))
10381038

1039+
let mklist lst startp endp =
1040+
let seq, ext_opt = lst in
1041+
let loc = mklocation startp endp in
1042+
make_real_exp (mktailexp_extension loc seq ext_opt)
1043+
10391044
%}
10401045

10411046

@@ -2618,12 +2623,30 @@ jsx_start_tag_and_args_without_leading_less:
26182623
(jsx_component lident $2, lident) }
26192624
;
26202625

2626+
jsx_expr_list:
2627+
LBRACKET expr_comma_seq_extension RBRACKET
2628+
{ mklist $2 $startpos($2) $endpos($2) }
2629+
2630+
jsx_children_including_list:
2631+
| simple_expr_no_call { $1 }
2632+
| jsx_expr_list { $1 }
2633+
26212634
jsx:
26222635
| LESSGREATER simple_expr_no_call* LESSSLASHGREATER
26232636
{ let loc = mklocation $symbolstartpos $endpos in
26242637
let body = mktailexp_extension loc $2 None in
26252638
makeFrag loc body
26262639
}
2640+
| LESSGREATER jsx_expr_list+ LESSSLASHGREATER
2641+
{ let loc = mklocation $symbolstartpos $endpos in
2642+
let body = mktailexp_extension loc $2 None in
2643+
makeFrag loc body
2644+
}
2645+
| LESSGREATER DOTDOTDOT jsx_children_including_list LESSSLASHGREATER
2646+
{ let loc = mklocation $symbolstartpos $endpos in
2647+
let body = $3 (*mktailexp_extension loc $3 None*) in
2648+
makeFrag loc body
2649+
}
26272650
| jsx_start_tag_and_args SLASHGREATER
26282651
{ let (component, _) = $1 in
26292652
let loc = mklocation $symbolstartpos $endpos in
@@ -2644,7 +2667,18 @@ jsx:
26442667
(Nolabel, mkexp_constructor_unit loc loc)
26452668
] loc
26462669
}
2647-
| jsx_start_tag_and_args GREATER DOTDOTDOT simple_expr_no_call LESSSLASHIDENTGREATER
2670+
| jsx_start_tag_and_args GREATER jsx_expr_list+ LESSSLASHIDENTGREATER
2671+
{ let (component, start) = $1 in
2672+
let loc = mklocation $symbolstartpos $endpos in
2673+
(* TODO: Make this tag check simply a warning *)
2674+
let endName = Longident.parse $4 in
2675+
let _ = ensureTagsAreEqual start endName loc in
2676+
component [
2677+
(Labelled "children", mktailexp_extension loc $3 None);
2678+
(Nolabel, mkexp_constructor_unit loc loc)
2679+
] loc
2680+
}
2681+
| jsx_start_tag_and_args GREATER DOTDOTDOT jsx_children_including_list LESSSLASHIDENTGREATER
26482682
(* <Foo> ...bar </Foo> or <Foo> ...((a) => 1) </Foo> *)
26492683
{ let (component, start) = $1 in
26502684
let loc = mklocation $symbolstartpos $endpos in
@@ -2665,6 +2699,16 @@ jsx_without_leading_less:
26652699
let body = mktailexp_extension loc $2 None in
26662700
makeFrag loc body
26672701
}
2702+
| GREATER jsx_expr_list+ LESSSLASHGREATER
2703+
{ let loc = mklocation $symbolstartpos $endpos in
2704+
let body = mktailexp_extension loc $2 None in
2705+
makeFrag loc body
2706+
}
2707+
| GREATER DOTDOTDOT jsx_children_including_list LESSSLASHGREATER
2708+
{ let loc = mklocation $symbolstartpos $endpos in
2709+
let body = $3 (*mktailexp_extension loc $3 None*) in
2710+
makeFrag loc body
2711+
}
26682712
| jsx_start_tag_and_args_without_leading_less SLASHGREATER {
26692713
let (component, _) = $1 in
26702714
let loc = mklocation $symbolstartpos $endpos in
@@ -2685,7 +2729,18 @@ jsx_without_leading_less:
26852729
(Nolabel, mkexp_constructor_unit loc loc)
26862730
] loc
26872731
}
2688-
| jsx_start_tag_and_args_without_leading_less GREATER DOTDOTDOT simple_expr_no_call LESSSLASHIDENTGREATER {
2732+
| jsx_start_tag_and_args_without_leading_less GREATER jsx_expr_list+ LESSSLASHIDENTGREATER
2733+
{ let (component, start) = $1 in
2734+
let loc = mklocation $symbolstartpos $endpos in
2735+
(* TODO: Make this tag check simply a warning *)
2736+
let endName = Longident.parse $4 in
2737+
let _ = ensureTagsAreEqual start endName loc in
2738+
component [
2739+
(Labelled "children", mktailexp_extension loc $3 None);
2740+
(Nolabel, mkexp_constructor_unit loc loc)
2741+
] loc
2742+
}
2743+
| jsx_start_tag_and_args_without_leading_less GREATER DOTDOTDOT jsx_children_including_list LESSSLASHIDENTGREATER {
26892744
let (component, start) = $1 in
26902745
let loc = mklocation $symbolstartpos $endpos in
26912746
(* TODO: Make this tag check simply a warning *)
@@ -3034,10 +3089,7 @@ simple_expr_call:
30343089
{ let (body, args) = $1 in
30353090
(body, List.rev_append $2 args) }
30363091
| LBRACKET expr_comma_seq_extension RBRACKET
3037-
{ let seq, ext_opt = $2 in
3038-
let loc = mklocation $startpos($2) $endpos($2) in
3039-
(make_real_exp (mktailexp_extension loc seq ext_opt), [])
3040-
}
3092+
{ (mklist $2 $startpos($2) $endpos($2), []) }
30413093
| simple_expr_template_constructor { ($1, []) }
30423094
;
30433095

‎src/reason-parser/reason_pprint_ast.ml‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5637,9 +5637,9 @@ let printer = object(self:'self)
56375637
| ({txt="JSX"; loc}, PStr []) :: _ ->
56385638
begin match self#simplest_expression x with
56395639
| Some r -> self#formatChildren remaining (r :: processedRev)
5640-
| None -> self#formatChildren (remaining @ children) processedRev
5640+
| None -> self#formatChildren (children @ remaining) processedRev
56415641
end
5642-
| _ -> self#formatChildren (remaining @ children) processedRev
5642+
| _ -> self#formatChildren (children @ remaining) processedRev
56435643
end
56445644
| {pexp_desc = Pexp_apply(expr, l); pexp_attributes} :: remaining ->
56455645
self#formatChildren remaining (self#simplifyUnparseExpr (List.hd children) :: processedRev)

0 commit comments

Comments
 (0)