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

Commit a0d8494

Browse files
committed
Fix issue with JSX V4 and newtype
This is a port of PR rescript-lang/rescript#6029
1 parent 52cfbb3 commit a0d8494

17 files changed

+113
-71
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
- Fix issue with using alias and default value together https://github.com/rescript-lang/syntax/pull/734
6565
- Fix formatting of `switch` expressions that contain braced `cases` inside https://github.com/rescript-lang/syntax/pull/735
6666
- Fix formatting of props spread for multiline JSX expression https://github.com/rescript-lang/syntax/pull/736
67+
- Fix issue with JSX V4 and newtype https://github.com/rescript-lang/syntax/pull/737
6768

6869
#### :eyeglasses: Spec Compliance
6970

cli/reactjs_jsx_v4.ml

+13-38
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ let makePropsTypeParams ?(stripExplicitOption = false)
277277
For example, if JSX ppx is used for React Native, type would be different.
278278
*)
279279
match interiorType with
280-
| {ptyp_desc = Ptyp_var "ref"} -> Some (refType loc)
280+
| {ptyp_desc = Ptyp_any} -> Some (refType loc)
281281
| _ ->
282282
(* Strip explicit Js.Nullable.t in case of forwardRef *)
283283
if stripExplicitJsNullableOfRef then stripJsNullable interiorType
@@ -687,46 +687,18 @@ let rec recursivelyTransformNamedArgsForMake mapper expr args newtypes coreType
687687
(Some coreType)
688688
| _ -> (args, newtypes, coreType)
689689

690-
let newtypeToVar newtype type_ =
691-
let var_desc = Ptyp_var ("type-" ^ newtype) in
692-
let typ (mapper : Ast_mapper.mapper) typ =
693-
match typ.ptyp_desc with
694-
| Ptyp_constr ({txt = Lident name}, _) when name = newtype ->
695-
{typ with ptyp_desc = var_desc}
696-
| _ -> Ast_mapper.default_mapper.typ mapper typ
697-
in
698-
let mapper = {Ast_mapper.default_mapper with typ} in
699-
mapper.typ mapper type_
700-
701-
let argToType ~newtypes ~(typeConstraints : core_type option) types
690+
let argToType types
702691
((name, default, {ppat_attributes = attrs}, _alias, loc, type_) :
703692
arg_label * expression option * pattern * label * 'loc * core_type option)
704693
=
705-
let rec getType name coreType =
706-
match coreType with
707-
| {ptyp_desc = Ptyp_arrow (arg, c1, c2)} ->
708-
if name = arg then Some c1 else getType name c2
709-
| _ -> None
710-
in
711-
let typeConst = Option.bind typeConstraints (getType name) in
712-
let type_ =
713-
List.fold_left
714-
(fun type_ newtype ->
715-
match (type_, typeConst) with
716-
| _, Some typ | Some typ, None -> Some (newtypeToVar newtype.txt typ)
717-
| _ -> None)
718-
type_ newtypes
719-
in
720694
match (type_, name, default) with
721695
| Some type_, name, _ when isOptional name ->
722696
(true, getLabel name, attrs, loc, type_) :: types
723697
| Some type_, name, _ -> (false, getLabel name, attrs, loc, type_) :: types
724698
| None, name, _ when isOptional name ->
725-
(true, getLabel name, attrs, loc, Typ.var ~loc (safeTypeFromValue name))
726-
:: types
699+
(true, getLabel name, attrs, loc, Typ.any ~loc ()) :: types
727700
| None, name, _ when isLabelled name ->
728-
(false, getLabel name, attrs, loc, Typ.var ~loc (safeTypeFromValue name))
729-
:: types
701+
(false, getLabel name, attrs, loc, Typ.any ~loc ()) :: types
730702
| _ -> types
731703

732704
let hasDefaultValue nameArgList =
@@ -1006,16 +978,12 @@ let transformStructureItem ~config mapper item =
1006978
modifiedBinding binding
1007979
in
1008980
(* do stuff here! *)
1009-
let namedArgList, newtypes, typeConstraints =
981+
let namedArgList, newtypes, _typeConstraints =
1010982
recursivelyTransformNamedArgsForMake mapper
1011983
(modifiedBindingOld binding)
1012984
[] [] None
1013985
in
1014-
let namedTypeList =
1015-
List.fold_left
1016-
(argToType ~newtypes ~typeConstraints)
1017-
[] namedArgList
1018-
in
986+
let namedTypeList = List.fold_left argToType [] namedArgList in
1019987
let vbMatch (name, default, _, alias, loc, _) =
1020988
let label = getLabel name in
1021989
match default with
@@ -1208,6 +1176,13 @@ let transformStructureItem ~config mapper item =
12081176
| _ -> [Typ.any ()]))))
12091177
expression
12101178
in
1179+
let expression =
1180+
(* Add new tupes (type a,b,c) to make's definition *)
1181+
newtypes
1182+
|> List.fold_left
1183+
(fun e newtype -> Exp.newtype newtype e)
1184+
expression
1185+
in
12111186
(* let make = ({id, name, ...}: props<'id, 'name, ...>) => { ... } *)
12121187
let bindings, newBinding =
12131188
match recFlag with

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

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ module C0 = {
44
type props<'priority, 'text> = {priority: 'priority, text?: 'text}
55

66
@react.component
7-
let make = (props: props<'priority, 'text>) => {
7+
let make = (props: props<_, _>) => {
88
let _ = props.priority
99
let text = switch props.text {
1010
| Some(text) => text
@@ -24,7 +24,7 @@ module C1 = {
2424
type props<'priority, 'text> = {priority: 'priority, text?: 'text}
2525

2626
@react.component
27-
let make = (props: props<'priority, 'text>) => {
27+
let make = (props: props<_, _>) => {
2828
let p = props.priority
2929
let text = switch props.text {
3030
| Some(text) => text
@@ -44,7 +44,7 @@ module C2 = {
4444
type props<'foo> = {foo?: 'foo}
4545

4646
@react.component
47-
let make = (props: props<'foo>) => {
47+
let make = (props: props<_>) => {
4848
let bar = switch props.foo {
4949
| Some(foo) => foo
5050
| None => ""

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
type props<'msg> = {msg: 'msg} // test React JSX file
22

33
@react.component
4-
let make = ({msg, _}: props<'msg>) => {
4+
let make = ({msg, _}: props<_>) => {
55
ReactDOM.jsx("div", {children: ?ReactDOM.someElement({msg->React.string})})
66
}
77
let make = {

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
module C0 = {
22
type props<'a, 'b> = {a?: 'a, b?: 'b}
33
@react.component
4-
let make = (props: props<'a, 'b>) => {
4+
let make = (props: props<_, _>) => {
55
let a = switch props.a {
66
| Some(a) => a
77
| None => 2
@@ -23,7 +23,7 @@ module C1 = {
2323
type props<'a, 'b> = {a?: 'a, b: 'b}
2424

2525
@react.component
26-
let make = (props: props<'a, 'b>) => {
26+
let make = (props: props<_, _>) => {
2727
let a = switch props.a {
2828
| Some(a) => a
2929
| None => 2

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ module V4C = {
2121
type props<'msg> = {msg: 'msg}
2222

2323
@react.component
24-
let make = ({msg, _}: props<'msg>) => {
24+
let make = ({msg, _}: props<_>) => {
2525
ReactDOM.createDOMElementVariadic("div", [{msg->React.string}])
2626
}
2727
let make = {
@@ -37,7 +37,7 @@ module V4A = {
3737
type props<'msg> = {msg: 'msg}
3838

3939
@react.component
40-
let make = ({msg, _}: props<'msg>) => {
40+
let make = ({msg, _}: props<_>) => {
4141
ReactDOM.jsx("div", {children: ?ReactDOM.someElement({msg->React.string})})
4242
}
4343
let make = {

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

+5-4
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,12 @@ module Select = {
6666

6767
@react.component
6868
let make = (
69+
type a key,
6970
{model, selected, onChange, items, _}: props<
70-
module(T with type t = '\"type-a" and type key = '\"type-key"),
71-
option<'\"type-key">,
72-
option<'\"type-key"> => unit,
73-
array<'\"type-a">,
71+
module(T with type t = a and type key = key),
72+
option<key>,
73+
option<key> => unit,
74+
array<a>,
7475
>,
7576
) => {
7677
let _ = (model, selected, onChange, items)

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

+2-5
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ module V4C = {
7777

7878
@react.component
7979
let make = (
80-
{?className, children, _}: props<'className, 'children, ReactRef.currentDomRef>,
80+
{?className, children, _}: props<_, _, ReactRef.currentDomRef>,
8181
ref: Js.Nullable.t<ReactRef.currentDomRef>,
8282
) =>
8383
ReactDOM.createDOMElementVariadic(
@@ -135,10 +135,7 @@ module V4A = {
135135
}
136136

137137
@react.component
138-
let make = (
139-
{?className, children, _}: props<'className, 'children, ReactDOM.Ref.currentDomRef>,
140-
ref,
141-
) =>
138+
let make = ({?className, children, _}: props<_, _, ReactDOM.Ref.currentDomRef>, ref) =>
142139
ReactDOM.jsxs(
143140
"div",
144141
{

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module A = {
22
type props<'x> = {x: 'x}
3-
@react.component let make = ({x, _}: props<'x>) => React.string(x)
3+
@react.component let make = ({x, _}: props<_>) => React.string(x)
44
let make = {
55
let \"Interface$A" = (props: props<_>) => make(props)
66
\"Interface$A"

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

+2-4
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,7 @@ module C4C0 = {
2323
type props<'T_open, 'T_type> = {@as("open") _open: 'T_open, @as("type") _type: 'T_type}
2424

2525
@react.component
26-
let make = ({@as("open") _open, @as("type") _type, _}: props<'T_open, string>) =>
27-
React.string(_open)
26+
let make = ({@as("open") _open, @as("type") _type, _}: props<_, string>) => React.string(_open)
2827
let make = {
2928
let \"MangleKeyword$C4C0" = (props: props<_>) => make(props)
3029

@@ -46,8 +45,7 @@ module C4A0 = {
4645
type props<'T_open, 'T_type> = {@as("open") _open: 'T_open, @as("type") _type: 'T_type}
4746

4847
@react.component
49-
let make = ({@as("open") _open, @as("type") _type, _}: props<'T_open, string>) =>
50-
React.string(_open)
48+
let make = ({@as("open") _open, @as("type") _type, _}: props<_, string>) => React.string(_open)
5149
let make = {
5250
let \"MangleKeyword$C4A0" = (props: props<_>) => make(props)
5351

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

+48-2
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ module V4C = {
2727
type props<'a, 'b, 'c> = {a: 'a, b: 'b, c: 'c}
2828

2929
@react.component
30-
let make = ({a, b, c, _}: props<'\"type-a", array<option<[#Foo('\"type-a")]>>, 'a>) =>
30+
let make = (type a, {a, b, c, _}: props<a, array<option<[#Foo(a)]>>, 'a>) =>
3131
ReactDOM.createDOMElementVariadic("div", [])
3232
let make = {
3333
let \"Newtype$V4C" = (props: props<_>) => make(props)
@@ -42,11 +42,57 @@ module V4A = {
4242
type props<'a, 'b, 'c> = {a: 'a, b: 'b, c: 'c}
4343

4444
@react.component
45-
let make = ({a, b, c, _}: props<'\"type-a", array<option<[#Foo('\"type-a")]>>, 'a>) =>
45+
let make = (type a, {a, b, c, _}: props<a, array<option<[#Foo(a)]>>, 'a>) =>
4646
ReactDOM.jsx("div", {})
4747
let make = {
4848
let \"Newtype$V4A" = (props: props<_>) => make(props)
4949

5050
\"Newtype$V4A"
5151
}
5252
}
53+
54+
module V4A1 = {
55+
type props<'a, 'b, 'c> = {a: 'a, b: 'b, c: 'c}
56+
57+
@react.component
58+
let make = (type x y, {a, b, c, _}: props<x, array<y>, 'a>) => ReactDOM.jsx("div", {})
59+
let make = {
60+
let \"Newtype$V4A1" = (props: props<_>) => make(props)
61+
62+
\"Newtype$V4A1"
63+
}
64+
}
65+
66+
module type T = {
67+
type t
68+
}
69+
70+
module V4A2 = {
71+
type props<'foo> = {foo: 'foo}
72+
73+
@react.component
74+
let make = (type a, {foo, _}: props<module(T with type t = a)>) => {
75+
module T = unpack(foo)
76+
ReactDOM.jsx("div", {})
77+
}
78+
let make = {
79+
let \"Newtype$V4A2" = (props: props<_>) => make(props)
80+
81+
\"Newtype$V4A2"
82+
}
83+
}
84+
85+
module V4A3 = {
86+
type props<'foo> = {foo: 'foo}
87+
88+
@react.component
89+
let make = (type a, {foo, _}: props<_>) => {
90+
module T = unpack(foo: T with type t = a)
91+
foo
92+
}
93+
let make = {
94+
let \"Newtype$V4A3" = (props: props<_>) => make(props)
95+
96+
\"Newtype$V4A3"
97+
}
98+
}

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ module User = {
77
type props<'doctor> = {doctor: 'doctor}
88

99
@react.component
10-
let make = ({doctor, _}: props<'doctor>) => {
10+
let make = ({doctor, _}: props<_>) => {
1111
ReactDOM.jsx("h1", {id: "h1", children: ?ReactDOM.someElement({React.string(format(doctor))})})
1212
}
1313
let make = {

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
module Foo = {
44
type props<'x, 'y> = {x: 'x, y: 'y}
55

6-
@react.component let make = ({x, y, _}: props<'x, 'y>) => React.string(x ++ y)
6+
@react.component let make = ({x, y, _}: props<_, _>) => React.string(x ++ y)
77
let make = {
88
let \"RemovedKeyProp$Foo" = (props: props<_>) => make(props)
99

@@ -15,7 +15,7 @@ module HasChildren = {
1515
type props<'children> = {children: 'children}
1616

1717
@react.component
18-
let make = ({children, _}: props<'children>) => ReactDOM.createElement(React.fragment, [children])
18+
let make = ({children, _}: props<_>) => ReactDOM.createElement(React.fragment, [children])
1919
let make = {
2020
let \"RemovedKeyProp$HasChildren" = (props: props<_>) => make(props)
2121

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ module V4C = {
2525
type props<'a, 'b> = {a: 'a, b: 'b}
2626

2727
@react.component
28-
let make = ({a, b, _}: props<'a, 'b>) => {
28+
let make = ({a, b, _}: props<_, _>) => {
2929
Js.log("This function should be named 'TopLevel.react'")
3030
ReactDOM.createDOMElementVariadic("div", [])
3131
}
@@ -42,7 +42,7 @@ module V4A = {
4242
type props<'a, 'b> = {a: 'a, b: 'b}
4343

4444
@react.component
45-
let make = ({a, b, _}: props<'a, 'b>) => {
45+
let make = ({a, b, _}: props<_, _>) => {
4646
Js.log("This function should be named 'TopLevel.react'")
4747
ReactDOM.jsx("div", {})
4848
}

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

+2-3
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@ module V4C = {
2020
type props<'a, 'b> = {a: 'a, b: 'b}
2121

2222
@react.component
23-
let make = ({a, b, _}: props<'\"type-a", '\"type-a">) =>
24-
ReactDOM.createDOMElementVariadic("div", [])
23+
let make = (type a, {a, b, _}: props<_, _>) => ReactDOM.createDOMElementVariadic("div", [])
2524
let make = {
2625
let \"TypeConstraint$V4C" = (props: props<_>) => make(props)
2726

@@ -34,7 +33,7 @@ module V4C = {
3433
module V4A = {
3534
type props<'a, 'b> = {a: 'a, b: 'b}
3635

37-
@react.component let make = ({a, b, _}: props<'\"type-a", '\"type-a">) => ReactDOM.jsx("div", {})
36+
@react.component let make = (type a, {a, b, _}: props<_, _>) => ReactDOM.jsx("div", {})
3837
let make = {
3938
let \"TypeConstraint$V4A" = (props: props<_>) => make(props)
4039

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ module AnotherName = {
99
type // Component with another name than "make"
1010
props<'x> = {x: 'x}
1111

12-
@react.component let anotherName = ({x, _}: props<'x>) => React.string(x)
12+
@react.component let anotherName = ({x, _}: props<_>) => React.string(x)
1313
let anotherName = {
1414
let \"V4$AnotherName$anotherName" = (props: props<_>) => anotherName(props)
1515

0 commit comments

Comments
 (0)