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

Commit a40b8b6

Browse files
authored
JSX v4 record-based representation for lowercase (#665)
* record-based representation for jsx lowercase * spread props for lowercase * update changelog * fix build
1 parent 5a54a86 commit a40b8b6

File tree

5 files changed

+49
-23
lines changed

5 files changed

+49
-23
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@
3939

4040
- Functions with consecutive dots now print as multiple arrow functions like in JavaScript.
4141

42+
#### :nail_care Polish
43+
44+
- Change the internal representation of props for the lowercase components to record. https://github.com/rescript-lang/syntax/pull/665
45+
4246
## ReScript 10.0
4347

4448
- Fix printing for inline nullary functor types [#477](https://github.com/rescript-lang/syntax/pull/477)

cli/reactjs_jsx_v4.ml

+13-17
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ let getLabel str =
2727
| Optional str | Labelled str -> str
2828
| Nolabel -> ""
2929

30-
let optionalAttr = [({txt = "ns.optional"; loc = Location.none}, PStr [])]
30+
let optionalAttr = ({txt = "ns.optional"; loc = Location.none}, PStr [])
31+
let optionalAttrs = [optionalAttr]
3132

3233
let constantString ~loc str =
3334
Ast_helper.Exp.constant ~loc (Pconst_string (str, None))
@@ -211,7 +212,7 @@ let recordFromProps ~loc ~removeKey callArguments =
211212
let id = getLabel arg_label in
212213
if isOptional arg_label then
213214
( {txt = Lident id; loc = pexp_loc},
214-
{pexpr with pexp_attributes = optionalAttr} )
215+
{pexpr with pexp_attributes = optionalAttrs} )
215216
else ({txt = Lident id; loc = pexp_loc}, pexpr)
216217
in
217218
let fields = props |> List.map processProp in
@@ -288,9 +289,9 @@ let makeLabelDecls ~loc namedTypeList =
288289
namedTypeList
289290
|> List.map (fun (isOptional, label, _, interiorType) ->
290291
if label = "key" then
291-
Type.field ~loc ~attrs:optionalAttr {txt = label; loc} interiorType
292+
Type.field ~loc ~attrs:optionalAttrs {txt = label; loc} interiorType
292293
else if isOptional then
293-
Type.field ~loc ~attrs:optionalAttr {txt = label; loc}
294+
Type.field ~loc ~attrs:optionalAttrs {txt = label; loc}
294295
(Typ.var @@ safeTypeFromValue @@ Labelled label)
295296
else
296297
Type.field ~loc {txt = label; loc}
@@ -462,7 +463,7 @@ let transformLowercaseCall3 ~config mapper jsxExprLoc callExprLoc attrs
462463
| Exact children ->
463464
[
464465
( labelled "children",
465-
Exp.apply ~attrs:optionalAttr
466+
Exp.apply ~attrs:optionalAttrs
466467
(Exp.ident
467468
{
468469
txt = Ldot (Lident "ReactDOM", "someElement");
@@ -543,19 +544,14 @@ let transformLowercaseCall3 ~config mapper jsxExprLoc callExprLoc attrs
543544
(nolabel, childrenExpr);
544545
]
545546
| nonEmptyProps ->
546-
let propsCall =
547-
Exp.apply
548-
(Exp.ident
549-
{loc = Location.none; txt = Ldot (Lident "ReactDOM", "domProps")})
550-
(nonEmptyProps
551-
|> List.map (fun (label, expression) ->
552-
(label, mapper.expr mapper expression)))
547+
let propsRecord =
548+
recordFromProps ~loc:Location.none ~removeKey:false nonEmptyProps
553549
in
554550
[
555551
(* "div" *)
556552
(nolabel, componentNameExpr);
557553
(* ReactDOM.domProps(~className=blabla, ~foo=bar, ()) *)
558-
(labelled "props", propsCall);
554+
(labelled "props", propsRecord);
559555
(* [|moreCreateElementCallsHere|] *)
560556
(nolabel, childrenExpr);
561557
]
@@ -688,14 +684,14 @@ let argToType ~newtypes ~(typeConstraints : core_type option) types
688684
in
689685
match (type_, name, default) with
690686
| Some type_, name, _ when isOptional name ->
691-
(true, getLabel name, [], {type_ with ptyp_attributes = optionalAttr})
687+
(true, getLabel name, [], {type_ with ptyp_attributes = optionalAttrs})
692688
:: types
693689
| Some type_, name, _ -> (false, getLabel name, [], type_) :: types
694690
| None, name, _ when isOptional name ->
695691
( true,
696692
getLabel name,
697693
[],
698-
Typ.var ~loc ~attrs:optionalAttr (safeTypeFromValue name) )
694+
Typ.var ~loc ~attrs:optionalAttrs (safeTypeFromValue name) )
699695
:: types
700696
| None, name, _ when isLabelled name ->
701697
(false, getLabel name, [], Typ.var ~loc (safeTypeFromValue name)) :: types
@@ -1052,7 +1048,7 @@ let transformStructureItem ~config mapper item =
10521048
{
10531049
patternWithoutConstraint with
10541050
ppat_attributes =
1055-
(if isOptional arg_label then optionalAttr else [])
1051+
(if isOptional arg_label then optionalAttrs else [])
10561052
@ pattern.ppat_attributes;
10571053
} )
10581054
:: patternsWithLabel)
@@ -1068,7 +1064,7 @@ let transformStructureItem ~config mapper item =
10681064
{
10691065
pattern with
10701066
ppat_attributes =
1071-
optionalAttr @ pattern.ppat_attributes;
1067+
optionalAttrs @ pattern.ppat_attributes;
10721068
} )
10731069
:: patternsWithNolabel)
10741070
expr

tests/ppx/react/expected/forwardRef.res.txt

+5-6
Original file line numberDiff line numberDiff line change
@@ -82,12 +82,11 @@ module V4C = {
8282
[
8383
ReactDOM.createDOMElementVariadic(
8484
"input",
85-
~props=ReactDOM.domProps(
86-
~type_="text",
87-
~className?,
88-
~ref=?{Js.Nullable.toOption(ref)->Belt.Option.map(React.Ref.domRef)},
89-
(),
90-
),
85+
~props={
86+
type_: "text",
87+
?className,
88+
ref: ?Js.Nullable.toOption(ref)->Belt.Option.map(React.Ref.domRef),
89+
},
9190
[],
9291
),
9392
children,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
@@jsxConfig({version: 4, mode: "classic"})
2+
3+
let _ = ReactDOM.createDOMElementVariadic("div", [])
4+
let _ = ReactDOM.createDOMElementVariadic("div", ~props={key: "k"}, [])
5+
let _ = ReactDOM.createDOMElementVariadic("div", ~props={x: x}, [])
6+
let _ = ReactDOM.createDOMElementVariadic(
7+
"div",
8+
[ReactDOM.createDOMElementVariadic("p", [{React.string(x)}])],
9+
)
10+
let _ = ReactDOM.createDOMElementVariadic("div", ~props=str, [])
11+
let _ = ReactDOM.createDOMElementVariadic("div", ~props={...str, x: "x"}, [])
12+
13+
// syntax error
14+
// let _ = <div x="x" {...str} />
15+
// let _ = <div {...str} {...str} />

tests/ppx/react/lowercases.res

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
@@jsxConfig({version:4, mode:"classic"})
2+
3+
let _ = <div />
4+
let _ = <div key="k" />
5+
let _ = <div x />
6+
let _ = <div><p>{React.string(x)}</p></div>
7+
let _ = <div {...str} />
8+
let _ = <div {...str} x="x" />
9+
10+
// syntax error
11+
// let _ = <div x="x" {...str} />
12+
// let _ = <div {...str} {...str} />

0 commit comments

Comments
 (0)