Skip to content
This repository was archived by the owner on Jun 15, 2023. It is now read-only.

Commit b30d3ba

Browse files
author
Iwan
committed
Implement jsx spread printing.
Fixes #364 Printing of `<Animated> ...{x => <div />} </Animated>` was not implemented
1 parent 07421c7 commit b30d3ba

File tree

4 files changed

+255
-28
lines changed

4 files changed

+255
-28
lines changed

src/res_printer.ml

Lines changed: 51 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3834,7 +3834,11 @@ and printJsxExpression lident args cmtTbl =
38343834
let name = printJsxName lident in
38353835
let (formattedProps, children) = printJsxProps args cmtTbl in
38363836
(* <div className="test" /> *)
3837-
let isSelfClosing = match children with | [] -> true | _ -> false in
3837+
let isSelfClosing =
3838+
match children with
3839+
| Some ({Parsetree.pexp_desc = Pexp_construct ({txt = Longident.Lident "[]"}, None)}) -> true
3840+
| _ -> false
3841+
in
38383842
Doc.group (
38393843
Doc.concat [
38403844
Doc.group (
@@ -3851,7 +3855,10 @@ and printJsxExpression lident args cmtTbl =
38513855
Doc.indent (
38523856
Doc.concat [
38533857
Doc.line;
3854-
printJsxChildren children cmtTbl;
3858+
(match children with
3859+
| Some childrenExpression -> printJsxChildren childrenExpression cmtTbl
3860+
| None -> Doc.nil
3861+
);
38553862
]
38563863
);
38573864
Doc.line;
@@ -3865,17 +3872,17 @@ and printJsxExpression lident args cmtTbl =
38653872
and printJsxFragment expr cmtTbl =
38663873
let opening = Doc.text "<>" in
38673874
let closing = Doc.text "</>" in
3868-
let (children, _) = ParsetreeViewer.collectListExpressions expr in
3875+
(* let (children, _) = ParsetreeViewer.collectListExpressions expr in *)
38693876
Doc.group (
38703877
Doc.concat [
38713878
opening;
3872-
begin match children with
3873-
| [] -> Doc.nil
3874-
| children ->
3879+
begin match expr.pexp_desc with
3880+
| Pexp_construct ({txt = Longident.Lident "[]"}, None) -> Doc.nil
3881+
| _ ->
38753882
Doc.indent (
38763883
Doc.concat [
38773884
Doc.line;
3878-
printJsxChildren children cmtTbl;
3885+
printJsxChildren expr cmtTbl;
38793886
]
38803887
)
38813888
end;
@@ -3884,29 +3891,46 @@ and printJsxFragment expr cmtTbl =
38843891
]
38853892
)
38863893

3887-
and printJsxChildren (children: Parsetree.expression list) cmtTbl =
3888-
Doc.group (
3889-
Doc.join ~sep:Doc.line (
3890-
List.map (fun (expr : Parsetree.expression) ->
3891-
let leadingLineCommentPresent = hasLeadingLineComment cmtTbl expr.pexp_loc in
3892-
let exprDoc = printExpressionWithComments expr cmtTbl in
3893-
match Parens.jsxChildExpr expr with
3894-
| Parenthesized | Braced _ ->
3895-
(* {(20: int)} make sure that we also protect the expression inside *)
3896-
let innerDoc = if Parens.bracedExpr expr then addParens exprDoc else exprDoc in
3897-
if leadingLineCommentPresent then
3898-
addBraces innerDoc
3899-
else
3900-
Doc.concat [Doc.lbrace; innerDoc; Doc.rbrace]
3901-
| Nothing -> exprDoc
3902-
) children
3894+
and printJsxChildren (childrenExpr : Parsetree.expression) cmtTbl =
3895+
match childrenExpr.pexp_desc with
3896+
| Pexp_construct ({txt = Longident.Lident "::"}, _) ->
3897+
let (children, _) = ParsetreeViewer.collectListExpressions childrenExpr in
3898+
Doc.group (
3899+
Doc.join ~sep:Doc.line (
3900+
List.map (fun (expr : Parsetree.expression) ->
3901+
let leadingLineCommentPresent = hasLeadingLineComment cmtTbl expr.pexp_loc in
3902+
let exprDoc = printExpressionWithComments expr cmtTbl in
3903+
match Parens.jsxChildExpr expr with
3904+
| Parenthesized | Braced _ ->
3905+
(* {(20: int)} make sure that we also protect the expression inside *)
3906+
let innerDoc = if Parens.bracedExpr expr then addParens exprDoc else exprDoc in
3907+
if leadingLineCommentPresent then
3908+
addBraces innerDoc
3909+
else
3910+
Doc.concat [Doc.lbrace; innerDoc; Doc.rbrace]
3911+
| Nothing -> exprDoc
3912+
) children
3913+
)
39033914
)
3904-
)
3915+
| _ ->
3916+
let leadingLineCommentPresent = hasLeadingLineComment cmtTbl childrenExpr.pexp_loc in
3917+
let exprDoc = printExpressionWithComments childrenExpr cmtTbl in
3918+
Doc.concat [
3919+
Doc.dotdotdot;
3920+
match Parens.jsxChildExpr childrenExpr with
3921+
| Parenthesized | Braced _ ->
3922+
let innerDoc = if Parens.bracedExpr childrenExpr then addParens exprDoc else exprDoc in
3923+
if leadingLineCommentPresent then
3924+
addBraces innerDoc
3925+
else
3926+
Doc.concat [Doc.lbrace; innerDoc; Doc.rbrace]
3927+
| Nothing -> exprDoc
3928+
]
39053929

3906-
and printJsxProps args cmtTbl =
3930+
and printJsxProps args cmtTbl :(Doc.t * Parsetree.expression option) =
39073931
let rec loop props args =
39083932
match args with
3909-
| [] -> (Doc.nil, [])
3933+
| [] -> (Doc.nil, None)
39103934
| [
39113935
(Asttypes.Labelled "children", children);
39123936
(
@@ -3925,8 +3949,7 @@ and printJsxProps args cmtTbl =
39253949
)
39263950
]
39273951
) in
3928-
let (children, _) = ParsetreeViewer.collectListExpressions children in
3929-
(formattedProps, children)
3952+
(formattedProps, Some children)
39303953
| arg::args ->
39313954
let propDoc = printJsxProp arg cmtTbl in
39323955
loop (propDoc::props) args

tests/printer/expr/__snapshots__/render.spec.js.snap

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3108,6 +3108,71 @@ module App = {
31083108
}
31093109
}
31103110
</div>
3111+
3112+
<Animated> ...{x => <div />} </Animated>
3113+
<div> ...c </div>
3114+
3115+
<Animated initialValue=0.0 value>
3116+
...{ReactDOMRe.Style.make(
3117+
~width=\\"20px\\",
3118+
~height=\\"20px\\",
3119+
~borderRadius=\\"100%\\",
3120+
~backgroundColor=\\"red\\",
3121+
)}
3122+
</Animated>
3123+
3124+
<Animated initialValue=0.0 value>
3125+
...{value =>
3126+
<div
3127+
style={ReactDOMRe.Style.make(
3128+
~width=\\"20px\\",
3129+
~height=\\"20px\\",
3130+
~borderRadius=\\"100%\\",
3131+
~backgroundColor=\\"red\\",
3132+
)}
3133+
/>}
3134+
</Animated>
3135+
3136+
<Animated initialValue=0.0 value>
3137+
...{(value): ReasonReact.element =>
3138+
<div
3139+
style={ReactDOMRe.Style.make(
3140+
~width=\\"20px\\",
3141+
~height=\\"20px\\",
3142+
~borderRadius=\\"100%\\",
3143+
~backgroundColor=\\"red\\",
3144+
)}
3145+
/>}
3146+
</Animated>
3147+
3148+
<Animated initialValue=0.0 value>
3149+
...{value => {
3150+
let width = \\"20px\\"
3151+
let height = \\"20px\\"
3152+
3153+
<div
3154+
style={ReactDOMRe.Style.make(
3155+
~width,
3156+
~height,
3157+
~borderRadius=\\"100%\\",
3158+
~backgroundColor=\\"red\\",
3159+
)}
3160+
/>
3161+
}}
3162+
</Animated>
3163+
3164+
let v =
3165+
<A>
3166+
<B>
3167+
...{_ => {
3168+
let renderX = x => {
3169+
let y = x ++ x
3170+
<div key=y />
3171+
}
3172+
renderX(\\"foo\\")
3173+
}}
3174+
</B>
3175+
</A>
31113176
"
31123177
`;
31133178

tests/printer/expr/expected/jsx.res.txt

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,3 +307,63 @@ module App = {
307307
}
308308
}
309309
</div>
310+
311+
<Animated> ...{x => <div />} </Animated>
312+
<div> ...c </div>
313+
314+
<Animated initialValue=0.0 value>
315+
...{ReactDOMRe.Style.make(
316+
~width="20px",
317+
~height="20px",
318+
~borderRadius="100%",
319+
~backgroundColor="red",
320+
)}
321+
</Animated>
322+
323+
<Animated initialValue=0.0 value>
324+
...{value =>
325+
<div
326+
style={ReactDOMRe.Style.make(
327+
~width="20px",
328+
~height="20px",
329+
~borderRadius="100%",
330+
~backgroundColor="red",
331+
)}
332+
/>}
333+
</Animated>
334+
335+
<Animated initialValue=0.0 value>
336+
...{(value): ReasonReact.element =>
337+
<div
338+
style={ReactDOMRe.Style.make(
339+
~width="20px",
340+
~height="20px",
341+
~borderRadius="100%",
342+
~backgroundColor="red",
343+
)}
344+
/>}
345+
</Animated>
346+
347+
<Animated initialValue=0.0 value>
348+
...{value => {
349+
let width = "20px"
350+
let height = "20px"
351+
352+
<div
353+
style={ReactDOMRe.Style.make(~width, ~height, ~borderRadius="100%", ~backgroundColor="red")}
354+
/>
355+
}}
356+
</Animated>
357+
358+
let v =
359+
<A>
360+
<B>
361+
...{_ => {
362+
let renderX = x => {
363+
let y = x ++ x
364+
<div key=y />
365+
}
366+
renderX("foo")
367+
}}
368+
</B>
369+
</A>

tests/printer/expr/jsx.res

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,3 +316,82 @@ module App = {
316316
}
317317
}
318318
</div>
319+
320+
<Animated> ...{x => <div />} </Animated>
321+
<div>...c</div>;
322+
323+
<Animated initialValue=0.0 value>
324+
...{
325+
ReactDOMRe.Style.make(
326+
~width="20px",
327+
~height="20px",
328+
~borderRadius="100%",
329+
~backgroundColor="red",
330+
)
331+
}
332+
</Animated>;
333+
334+
<Animated initialValue=0.0 value>
335+
...{
336+
value =>
337+
<div
338+
style={
339+
ReactDOMRe.Style.make(
340+
~width="20px",
341+
~height="20px",
342+
~borderRadius="100%",
343+
~backgroundColor="red",
344+
)
345+
}
346+
/>
347+
}
348+
</Animated>
349+
350+
<Animated initialValue=0.0 value>
351+
...{
352+
(value) :ReasonReact.element =>
353+
<div
354+
style={
355+
ReactDOMRe.Style.make(
356+
~width="20px",
357+
~height="20px",
358+
~borderRadius="100%",
359+
~backgroundColor="red",
360+
)
361+
}
362+
/>
363+
}
364+
</Animated>;
365+
366+
<Animated initialValue=0.0 value>
367+
...{value => {
368+
let width = "20px"
369+
let height = "20px"
370+
371+
<div
372+
style={
373+
ReactDOMRe.Style.make(
374+
~width,
375+
~height,
376+
~borderRadius="100%",
377+
~backgroundColor="red",
378+
)
379+
}
380+
/>
381+
}
382+
}
383+
</Animated>
384+
385+
386+
let v =
387+
<A>
388+
<B>
389+
...{_ => {
390+
let renderX = x => {
391+
let y = x ++ x;
392+
<div key=y />;
393+
}
394+
renderX("foo")
395+
}}
396+
</B>
397+
</A>

0 commit comments

Comments
 (0)