Skip to content

Commit 9d77da3

Browse files
committed
Parse list and list spread in JSX
fixes reasonml#1467
1 parent fe79b90 commit 9d77da3

File tree

7 files changed

+4761
-4360
lines changed

7 files changed

+4761
-4360
lines changed

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: 4678 additions & 4352 deletions
Large diffs are not rendered by default.

src/reason-parser/reason_parser.mly

Lines changed: 59 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1102,6 +1102,12 @@ let package_type_of_module_type pmty =
11021102
| _ ->
11031103
err pmty.pmty_loc
11041104
"only module type identifier and 'with type' constraints are supported"
1105+
1106+
let mklist lst startp endp =
1107+
let seq, ext_opt = lst in
1108+
let loc = mklocation startp endp in
1109+
make_real_exp (mktailexp_extension loc seq ext_opt)
1110+
11051111
%}
11061112

11071113

@@ -2684,12 +2690,30 @@ jsx_start_tag_and_args_without_leading_less:
26842690
(jsx_component lident $2, lident) }
26852691
;
26862692

2693+
jsx_expr_list:
2694+
LBRACKET expr_comma_seq_extension RBRACKET
2695+
{ mklist $2 $startpos($2) $endpos($2) }
2696+
2697+
jsx_children_including_list:
2698+
| simple_expr_no_call { $1 }
2699+
| jsx_expr_list { $1 }
2700+
26872701
jsx:
26882702
| LESSGREATER simple_expr_no_call* LESSSLASHGREATER
26892703
{ let loc = mklocation $symbolstartpos $endpos in
26902704
let body = mktailexp_extension loc $2 None in
26912705
makeFrag loc body
26922706
}
2707+
| LESSGREATER jsx_expr_list+ LESSSLASHGREATER
2708+
{ let loc = mklocation $symbolstartpos $endpos in
2709+
let body = mktailexp_extension loc $2 None in
2710+
makeFrag loc body
2711+
}
2712+
| LESSGREATER DOTDOTDOT jsx_children_including_list LESSSLASHGREATER
2713+
{ let loc = mklocation $symbolstartpos $endpos in
2714+
let body = $3 (*mktailexp_extension loc $3 None*) in
2715+
makeFrag loc body
2716+
}
26932717
| jsx_start_tag_and_args SLASHGREATER
26942718
{ let (component, _) = $1 in
26952719
let loc = mklocation $symbolstartpos $endpos in
@@ -2710,7 +2734,18 @@ jsx:
27102734
(Nolabel, mkexp_constructor_unit loc loc)
27112735
] loc
27122736
}
2713-
| jsx_start_tag_and_args GREATER DOTDOTDOT simple_expr_no_call LESSSLASHIDENTGREATER
2737+
| jsx_start_tag_and_args GREATER jsx_expr_list+ LESSSLASHIDENTGREATER
2738+
{ let (component, start) = $1 in
2739+
let loc = mklocation $symbolstartpos $endpos in
2740+
(* TODO: Make this tag check simply a warning *)
2741+
let endName = Longident.parse $4 in
2742+
let _ = ensureTagsAreEqual start endName loc in
2743+
component [
2744+
(Labelled "children", mktailexp_extension loc $3 None);
2745+
(Nolabel, mkexp_constructor_unit loc loc)
2746+
] loc
2747+
}
2748+
| jsx_start_tag_and_args GREATER DOTDOTDOT jsx_children_including_list LESSSLASHIDENTGREATER
27142749
(* <Foo> ...bar </Foo> or <Foo> ...((a) => 1) </Foo> *)
27152750
{ let (component, start) = $1 in
27162751
let loc = mklocation $symbolstartpos $endpos in
@@ -2731,6 +2766,16 @@ jsx_without_leading_less:
27312766
let body = mktailexp_extension loc $2 None in
27322767
makeFrag loc body
27332768
}
2769+
| GREATER jsx_expr_list+ LESSSLASHGREATER
2770+
{ let loc = mklocation $symbolstartpos $endpos in
2771+
let body = mktailexp_extension loc $2 None in
2772+
makeFrag loc body
2773+
}
2774+
| GREATER DOTDOTDOT jsx_children_including_list LESSSLASHGREATER
2775+
{ let loc = mklocation $symbolstartpos $endpos in
2776+
let body = $3 (*mktailexp_extension loc $3 None*) in
2777+
makeFrag loc body
2778+
}
27342779
| jsx_start_tag_and_args_without_leading_less SLASHGREATER {
27352780
let (component, _) = $1 in
27362781
let loc = mklocation $symbolstartpos $endpos in
@@ -2751,7 +2796,18 @@ jsx_without_leading_less:
27512796
(Nolabel, mkexp_constructor_unit loc loc)
27522797
] loc
27532798
}
2754-
| jsx_start_tag_and_args_without_leading_less GREATER DOTDOTDOT simple_expr_no_call LESSSLASHIDENTGREATER {
2799+
| jsx_start_tag_and_args_without_leading_less GREATER jsx_expr_list+ LESSSLASHIDENTGREATER
2800+
{ let (component, start) = $1 in
2801+
let loc = mklocation $symbolstartpos $endpos in
2802+
(* TODO: Make this tag check simply a warning *)
2803+
let endName = Longident.parse $4 in
2804+
let _ = ensureTagsAreEqual start endName loc in
2805+
component [
2806+
(Labelled "children", mktailexp_extension loc $3 None);
2807+
(Nolabel, mkexp_constructor_unit loc loc)
2808+
] loc
2809+
}
2810+
| jsx_start_tag_and_args_without_leading_less GREATER DOTDOTDOT jsx_children_including_list LESSSLASHIDENTGREATER {
27552811
let (component, start) = $1 in
27562812
let loc = mklocation $symbolstartpos $endpos in
27572813
(* TODO: Make this tag check simply a warning *)
@@ -3106,10 +3162,7 @@ simple_expr_call:
31063162
{ let (body, args) = $1 in
31073163
(body, List.rev_append $2 args) }
31083164
| LBRACKET expr_comma_seq_extension RBRACKET
3109-
{ let seq, ext_opt = $2 in
3110-
let loc = mklocation $startpos($2) $endpos($2) in
3111-
(make_real_exp (mktailexp_extension loc seq ext_opt), [])
3112-
}
3165+
{ (mklist $2 $startpos($2) $endpos($2), []) }
31133166
| simple_expr_template_constructor { ($1, []) }
31143167
;
31153168

src/reason-parser/reason_pprint_ast.ml

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

0 commit comments

Comments
 (0)