diff --git a/compiler/syntax/src/jsx_v4.ml b/compiler/syntax/src/jsx_v4.ml index e73db9f21c..76f2607fd2 100644 --- a/compiler/syntax/src/jsx_v4.ml +++ b/compiler/syntax/src/jsx_v4.ml @@ -920,6 +920,61 @@ let vb_match_expr named_arg_list expr = in aux (List.rev named_arg_list) +let vb_type_annotation ~expr (name, default, pattern, alias, loc, core_type) = + let label = get_label name in + let pattern_name = + match default with + | Some _ -> "__" ^ alias + | None -> alias + in + let value_binding = + Vb.mk ~loc + (match pattern with + | { + ppat_desc = + Ppat_constraint (pattern, ({ptyp_desc = Ptyp_package _} as type_)); + } -> + (* Handle pattern: ~comp as module(Comp: Comp) *) + Pat.record + [ + ( {txt = Lident label; loc = Location.none}, + Pat.constraint_ pattern type_ ); + ] + Closed + | _ -> ( + (* For other cases, use regular variable pattern with type constraint *) + let type_ = + match pattern with + | {ppat_desc = Ppat_constraint (_, type_)} -> Some type_ + | _ -> core_type + in + match type_ with + | Some type_ -> + Pat.constraint_ (Pat.var (Location.mkloc pattern_name loc)) type_ + | None -> Pat.var (Location.mkloc pattern_name loc))) + (match pattern with + | {ppat_desc = Ppat_constraint (_, {ptyp_desc = Ptyp_package _})} -> + (* For module types, use props directly *) + Exp.ident {txt = Lident "props"; loc = Location.none} + | _ -> + (* For other cases, use props.x form *) + Exp.field + (Exp.ident {txt = Lident "props"; loc = Location.none}) + {txt = Lident label; loc = Location.none}) + in + Exp.let_ Nonrecursive [value_binding] expr + +let vb_type_annotations_expr named_arg_list expr = + let rec aux named_arg_list = + match named_arg_list with + | [] -> expr + | ((name, _, _, _, _, _) as named_arg) :: rest -> + let label = get_label name in + if label = "ref" then aux rest + else vb_type_annotation named_arg ~expr:(aux rest) + in + aux (List.rev named_arg_list) + let map_binding ~config ~empty_loc ~pstr_loc ~file_name ~rec_flag binding = if Jsx_common.has_attr_on_binding binding then ( check_multiple_components ~config ~loc:pstr_loc; @@ -1105,6 +1160,8 @@ let map_binding ~config ~empty_loc ~pstr_loc ~file_name ~rec_flag binding = vb_match_expr named_arg_list expression else expression in + (* add pattern matching for optional prop value and type annotations *) + let expression = vb_type_annotations_expr named_arg_list expression in (* (ref) => expr *) let expression = List.fold_left @@ -1118,11 +1175,11 @@ let map_binding ~config ~empty_loc ~pstr_loc ~file_name ~rec_flag binding = Exp.fun_ Nolabel None pattern expr) expression patterns_with_nolabel in - (* ({a, b, _}: props<'a, 'b>) *) + (* (props: props<'a, 'b>) *) let record_pattern = match patterns_with_label with - | [] -> Pat.any () - | _ -> Pat.record (List.rev patterns_with_label) Open + | [] -> Pat.any () (* (_: props<'a, 'b>)*) + | _ -> Pat.var @@ Location.mknoloc "props" in let expression = Exp.fun_ Nolabel None diff --git a/tests/build_tests/react_ppx/src/recursive_component_test.bs.js b/tests/build_tests/react_ppx/src/recursive_component_test.bs.js index c24783b0fa..5c071e1f2f 100644 --- a/tests/build_tests/react_ppx/src/recursive_component_test.bs.js +++ b/tests/build_tests/react_ppx/src/recursive_component_test.bs.js @@ -9,8 +9,9 @@ function mm(x) { } function make(props) { + let b = props.b; return mm({ - b: props.b + b: b }); } diff --git a/tests/syntax_tests/data/ppx/react/expected/aliasProps.res.txt b/tests/syntax_tests/data/ppx/react/expected/aliasProps.res.txt index 02248a9072..c4174a72c8 100644 --- a/tests/syntax_tests/data/ppx/react/expected/aliasProps.res.txt +++ b/tests/syntax_tests/data/ppx/react/expected/aliasProps.res.txt @@ -4,7 +4,9 @@ module C0 = { @res.jsxComponentProps type props<'priority, 'text> = {priority: 'priority, text?: 'text} - let make = ({priority: _, text: ?__text, _}: props<_, _>) => { + let make = (props: props<_, _>) => { + let _ = props.priority + let __text = props.text let text = switch __text { | Some(text) => text | None => "Test" @@ -23,7 +25,9 @@ module C1 = { @res.jsxComponentProps type props<'priority, 'text> = {priority: 'priority, text?: 'text} - let make = ({priority: p, text: ?__text, _}: props<_, _>) => { + let make = (props: props<_, _>) => { + let p = props.priority + let __text = props.text let text = switch __text { | Some(text) => text | None => "Test" @@ -42,7 +46,8 @@ module C2 = { @res.jsxComponentProps type props<'foo> = {foo?: 'foo} - let make = ({foo: ?__bar, _}: props<_>) => { + let make = (props: props<_>) => { + let __bar = props.foo let bar = switch __bar { | Some(foo) => foo | None => "" @@ -61,7 +66,10 @@ module C3 = { @res.jsxComponentProps type props<'foo, 'a, 'b> = {foo?: 'foo, a?: 'a, b: 'b} - let make = ({foo: ?__bar, a: ?__a, b, _}: props<_, _, _>) => { + let make = (props: props<_, _, _>) => { + let __bar = props.foo + let __a = props.a + let b = props.b let bar = switch __bar { | Some(foo) => foo | None => "" @@ -86,7 +94,9 @@ module C4 = { @res.jsxComponentProps type props<'a, 'x> = {a: 'a, x?: 'x} - let make = ({a: b, x: ?__x, _}: props<_, _>) => { + let make = (props: props<_, _>) => { + let b = props.a + let __x = props.x let x = switch __x { | Some(x) => x | None => true @@ -105,7 +115,9 @@ module C5 = { @res.jsxComponentProps type props<'a, 'z> = {a: 'a, z?: 'z} - let make = ({a: (x, y), z: ?__z, _}: props<_, _>) => { + let make = (props: props<_, _>) => { + let a = props.a + let __z = props.z let z = switch __z { | Some(z) => z | None => 3 @@ -130,7 +142,11 @@ module C6 = { @res.jsxComponentProps type props<'comp, 'x> = {comp: 'comp, x: 'x} - let make = ({comp: module(Comp: Comp), x: (a, b), _}: props<_, _>) => React.jsx(Comp.make, {}) + let make = (props: props<_, _>) => { + let {comp: module(Comp: Comp)} = props + let x = props.x + React.jsx(Comp.make, {}) + } let make = { let \"AliasProps$C6" = (props: props<_>) => make(props) diff --git a/tests/syntax_tests/data/ppx/react/expected/asyncAwait.res.txt b/tests/syntax_tests/data/ppx/react/expected/asyncAwait.res.txt index 37df951e28..7311b6401f 100644 --- a/tests/syntax_tests/data/ppx/react/expected/asyncAwait.res.txt +++ b/tests/syntax_tests/data/ppx/react/expected/asyncAwait.res.txt @@ -4,7 +4,8 @@ module C0 = { @res.jsxComponentProps type props<'a> = {a: 'a} - let make = async ({a, _}: props<_>) => { + let make = async (props: props<_>) => { + let a = props.a let a = await f(a) ReactDOM.jsx("div", {children: ?ReactDOM.someElement({React.int(a)})}) } @@ -19,10 +20,13 @@ module C1 = { @res.jsxComponentProps type props<'status> = {status: 'status} - let make = async ({status, _}: props<_>) => { - switch status { - | #on => React.string("on") - | #off => React.string("off") + let make = async (props: props<_>) => { + let status = props.status + { + switch status { + | #on => React.string("on") + | #off => React.string("off") + } } } let make = { diff --git a/tests/syntax_tests/data/ppx/react/expected/commentAtTop.res.txt b/tests/syntax_tests/data/ppx/react/expected/commentAtTop.res.txt index 3f4656ddda..c6d4711f4b 100644 --- a/tests/syntax_tests/data/ppx/react/expected/commentAtTop.res.txt +++ b/tests/syntax_tests/data/ppx/react/expected/commentAtTop.res.txt @@ -1,8 +1,11 @@ @res.jsxComponentProps type props<'msg> = {msg: 'msg} // test React JSX file -let make = ({msg, _}: props<_>) => { - ReactDOM.jsx("div", {children: ?ReactDOM.someElement({msg->React.string})}) +let make = (props: props<_>) => { + let msg = props.msg + { + ReactDOM.jsx("div", {children: ?ReactDOM.someElement({msg->React.string})}) + } } let make = { let \"CommentAtTop" = (props: props<_>) => make(props) diff --git a/tests/syntax_tests/data/ppx/react/expected/defaultValueProp.res.txt b/tests/syntax_tests/data/ppx/react/expected/defaultValueProp.res.txt index 5cb93d4681..97657fc88b 100644 --- a/tests/syntax_tests/data/ppx/react/expected/defaultValueProp.res.txt +++ b/tests/syntax_tests/data/ppx/react/expected/defaultValueProp.res.txt @@ -1,7 +1,9 @@ module C0 = { @res.jsxComponentProps type props<'a, 'b> = {a?: 'a, b?: 'b} - let make = ({a: ?__a, b: ?__b, _}: props<_, _>) => { + let make = (props: props<_, _>) => { + let __a = props.a + let __b = props.b let a = switch __a { | Some(a) => a | None => 2 @@ -23,7 +25,9 @@ module C1 = { @res.jsxComponentProps type props<'a, 'b> = {a?: 'a, b: 'b} - let make = ({a: ?__a, b, _}: props<_, _>) => { + let make = (props: props<_, _>) => { + let __a = props.a + let b = props.b let a = switch __a { | Some(a) => a | None => 2 @@ -43,7 +47,8 @@ module C2 = { @res.jsxComponentProps type props<'a> = {a?: 'a} - let make = ({a: ?__a, _}: props<_>) => { + let make = (props: props<_>) => { + let __a = props.a let a = switch __a { | Some(a) => a | None => a @@ -62,7 +67,8 @@ module C3 = { @res.jsxComponentProps type props<'disabled> = {disabled?: 'disabled} - let make = ({disabled: ?__everythingDisabled, _}: props) => { + let make = (props: props) => { + let __everythingDisabled: bool = props.disabled let everythingDisabled = switch __everythingDisabled { | Some(disabled) => disabled | None => false diff --git a/tests/syntax_tests/data/ppx/react/expected/fileLevelConfig.res.txt b/tests/syntax_tests/data/ppx/react/expected/fileLevelConfig.res.txt index a69192fa65..eccccea6a9 100644 --- a/tests/syntax_tests/data/ppx/react/expected/fileLevelConfig.res.txt +++ b/tests/syntax_tests/data/ppx/react/expected/fileLevelConfig.res.txt @@ -4,8 +4,11 @@ module V4C = { @res.jsxComponentProps type props<'msg> = {msg: 'msg} - let make = ({msg, _}: props<_>) => { - ReactDOM.createDOMElementVariadic("div", [{msg->React.string}]) + let make = (props: props<_>) => { + let msg = props.msg + { + ReactDOM.createDOMElementVariadic("div", [{msg->React.string}]) + } } let make = { let \"FileLevelConfig$V4C" = (props: props<_>) => make(props) @@ -20,8 +23,11 @@ module V4A = { @res.jsxComponentProps type props<'msg> = {msg: 'msg} - let make = ({msg, _}: props<_>) => { - ReactDOM.jsx("div", {children: ?ReactDOM.someElement({msg->React.string})}) + let make = (props: props<_>) => { + let msg = props.msg + { + ReactDOM.jsx("div", {children: ?ReactDOM.someElement({msg->React.string})}) + } } let make = { let \"FileLevelConfig$V4A" = (props: props<_>) => make(props) diff --git a/tests/syntax_tests/data/ppx/react/expected/firstClassModules.res.txt b/tests/syntax_tests/data/ppx/react/expected/firstClassModules.res.txt index 934880c83a..18b363df3f 100644 --- a/tests/syntax_tests/data/ppx/react/expected/firstClassModules.res.txt +++ b/tests/syntax_tests/data/ppx/react/expected/firstClassModules.res.txt @@ -13,15 +13,12 @@ module Select = { items: 'items, } - let make = ( - type a key, - {model: module(T: T with type t = a and type key = key), selected, onChange, items, _}: props< - _, - option, - option => unit, - array, - >, - ) => { + let make = (type a key, props: props<_, option, option => unit, array>) => { + let {model: module(T: T with type t = a and type key = key)} = props + let selected: option = props.selected + let onChange: option => unit = props.onChange + let items: array = props.items + let _ = (model, selected, onChange, items) ReactDOM.createDOMElementVariadic("div", []) } @@ -32,6 +29,29 @@ module Select = { } } +module C6 = { + module type Comp = { + let xx: int + @res.jsxComponentProps + type props = {} + + let make: React.componentLike + } + @res.jsxComponentProps + type props<'comp, 'x> = {comp: 'comp, x: 'x} + + let make = (props: props<_, _>) => { + let {comp: module(Comp: Comp)} = props + let x = props.x + Comp.xx + } + let make = { + let \"FirstClassModules$C6" = (props: props<_>) => make(props) + + \"FirstClassModules$C6" + } +} + module External = { module type T = { type key diff --git a/tests/syntax_tests/data/ppx/react/expected/forwardRef.res.txt b/tests/syntax_tests/data/ppx/react/expected/forwardRef.res.txt index 4ea9cba48c..a2d641072a 100644 --- a/tests/syntax_tests/data/ppx/react/expected/forwardRef.res.txt +++ b/tests/syntax_tests/data/ppx/react/expected/forwardRef.res.txt @@ -10,9 +10,11 @@ module V4C = { } let make = ( - {?className, children, _}: props<_, _, ReactRef.currentDomRef>, + props: props<_, _, ReactRef.currentDomRef>, ref: Js.Nullable.t, - ) => + ) => { + let className = props.className + let children = props.children ReactDOM.createDOMElementVariadic( "div", [ @@ -28,6 +30,7 @@ module V4C = { children, ], ) + } let make = React.forwardRef({ let \"ForwardRef$V4C$FancyInput" = (props: props<_>, ref) => make(props, ref) @@ -67,9 +70,11 @@ module V4CUncurried = { } let make = ( - {?className, children, _}: props<_, _, ReactRef.currentDomRef>, + props: props<_, _, ReactRef.currentDomRef>, ref: Js.Nullable.t, - ) => + ) => { + let className = props.className + let children = props.children ReactDOM.createDOMElementVariadic( "div", [ @@ -85,6 +90,7 @@ module V4CUncurried = { children, ], ) + } let make = React.forwardRef({ let \"ForwardRef$V4CUncurried$FancyInput" = (props: props<_>, ref) => make(props, ref) @@ -125,7 +131,9 @@ module V4A = { ref?: 'ref, } - let make = ({?className, children, _}: props<_, _, 'ref>, ref: Js.Nullable.t<'ref>) => + let make = (props: props<_, _, 'ref>, ref: Js.Nullable.t<'ref>) => { + let className = props.className + let children = props.children ReactDOM.jsxs( "div", { @@ -142,6 +150,7 @@ module V4A = { ]), }, ) + } let make = React.forwardRef({ let \"ForwardRef$V4A$FancyInput" = (props: props<_>, ref) => make(props, ref) @@ -179,7 +188,9 @@ module V4AUncurried = { ref?: 'ref, } - let make = ({?className, children, _}: props<_, _, 'ref>, ref: Js.Nullable.t<'ref>) => + let make = (props: props<_, _, 'ref>, ref: Js.Nullable.t<'ref>) => { + let className = props.className + let children = props.children ReactDOM.jsxs( "div", { @@ -196,6 +207,7 @@ module V4AUncurried = { ]), }, ) + } let make = React.forwardRef({ let \"ForwardRef$V4AUncurried$FancyInput" = (props: props<_>, ref) => make(props, ref) diff --git a/tests/syntax_tests/data/ppx/react/expected/interface.res.txt b/tests/syntax_tests/data/ppx/react/expected/interface.res.txt index 645636451e..677bac5afb 100644 --- a/tests/syntax_tests/data/ppx/react/expected/interface.res.txt +++ b/tests/syntax_tests/data/ppx/react/expected/interface.res.txt @@ -1,7 +1,10 @@ module A = { @res.jsxComponentProps type props<'x> = {x: 'x} - let make = ({x, _}: props<_>) => React.string(x) + let make = (props: props<_>) => { + let x = props.x + React.string(x) + } let make = { let \"Interface$A" = (props: props<_>) => make(props) \"Interface$A" diff --git a/tests/syntax_tests/data/ppx/react/expected/interfaceWithRef.res.txt b/tests/syntax_tests/data/ppx/react/expected/interfaceWithRef.res.txt index eb7616f71f..a4e603c715 100644 --- a/tests/syntax_tests/data/ppx/react/expected/interfaceWithRef.res.txt +++ b/tests/syntax_tests/data/ppx/react/expected/interfaceWithRef.res.txt @@ -1,8 +1,9 @@ @res.jsxComponentProps type props<'x, 'ref> = {x: 'x, ref?: 'ref} let make = ( - {x, _}: props, + props: props, ref: Js.Nullable.t, ) => { + let x: string = props.x let _ = ref->Js.Nullable.toOption->Belt.Option.map(ReactDOM.Ref.domRef) React.string(x) } diff --git a/tests/syntax_tests/data/ppx/react/expected/mangleKeyword.res.txt b/tests/syntax_tests/data/ppx/react/expected/mangleKeyword.res.txt index 9c42648632..9394228343 100644 --- a/tests/syntax_tests/data/ppx/react/expected/mangleKeyword.res.txt +++ b/tests/syntax_tests/data/ppx/react/expected/mangleKeyword.res.txt @@ -4,7 +4,11 @@ module C4C0 = { @res.jsxComponentProps type props<'T_open, 'T_type> = {@as("open") _open: 'T_open, @as("type") _type: 'T_type} - let make = ({@as("open") _open, @as("type") _type, _}: props<_, string>) => React.string(_open) + let make = (props: props<_, string>) => { + let _open = props._open + let _type: string = props._type + React.string(_open) + } let make = { let \"MangleKeyword$C4C0" = (props: props<_>) => make(props) @@ -27,7 +31,11 @@ module C4A0 = { @res.jsxComponentProps type props<'T_open, 'T_type> = {@as("open") _open: 'T_open, @as("type") _type: 'T_type} - let make = ({@as("open") _open, @as("type") _type, _}: props<_, string>) => React.string(_open) + let make = (props: props<_, string>) => { + let _open = props._open + let _type: string = props._type + React.string(_open) + } let make = { let \"MangleKeyword$C4A0" = (props: props<_>) => make(props) diff --git a/tests/syntax_tests/data/ppx/react/expected/newtype.res.txt b/tests/syntax_tests/data/ppx/react/expected/newtype.res.txt index afc0ad4f8d..8023a6031f 100644 --- a/tests/syntax_tests/data/ppx/react/expected/newtype.res.txt +++ b/tests/syntax_tests/data/ppx/react/expected/newtype.res.txt @@ -4,8 +4,12 @@ module V4C = { @res.jsxComponentProps type props<'a, 'b, 'c> = {a: 'a, b: 'b, c: 'c} - let make = (type a, {a, b, c, _}: props>, 'a>) => + let make = (type a, props: props>, 'a>) => { + let a: a = props.a + let b: array> = props.b + let c: 'a = props.c ReactDOM.createDOMElementVariadic("div", []) + } let make = { let \"Newtype$V4C" = (props: props<_>) => make(props) @@ -19,8 +23,12 @@ module V4A = { @res.jsxComponentProps type props<'a, 'b, 'c> = {a: 'a, b: 'b, c: 'c} - let make = (type a, {a, b, c, _}: props>, 'a>) => + let make = (type a, props: props>, 'a>) => { + let a: a = props.a + let b: array> = props.b + let c: 'a = props.c ReactDOM.jsx("div", {}) + } let make = { let \"Newtype$V4A" = (props: props<_>) => make(props) @@ -32,7 +40,12 @@ module V4A1 = { @res.jsxComponentProps type props<'a, 'b, 'c> = {a: 'a, b: 'b, c: 'c} - let make = (type x y, {a, b, c, _}: props, 'a>) => ReactDOM.jsx("div", {}) + let make = (type x y, props: props, 'a>) => { + let a: x = props.a + let b: array = props.b + let c: 'a = props.c + ReactDOM.jsx("div", {}) + } let make = { let \"Newtype$V4A1" = (props: props<_>) => make(props) @@ -48,7 +61,8 @@ module V4A2 = { @res.jsxComponentProps type props<'foo> = {foo: 'foo} - let make = (type a, {foo: (foo: module(T with type t = a)), _}: props<_>) => { + let make = (type a, props: props<_>) => { + let {foo: (foo: module(T with type t = a))} = props module T = unpack(foo) ReactDOM.jsx("div", {}) } @@ -63,7 +77,8 @@ module V4A3 = { @res.jsxComponentProps type props<'foo> = {foo: 'foo} - let make = (type a, {foo, _}: props<_>) => { + let make = (type a, props: props<_>) => { + let foo = props.foo module T = unpack(foo: T with type t = a) foo } @@ -76,7 +91,11 @@ module V4A3 = { @res.jsxComponentProps type props<'x, 'q> = {x: 'x, q: 'q} -let make = ({x, q, _}: props<('a, 'b), 'a>) => [fst(x), q] +let make = (props: props<('a, 'b), 'a>) => { + let x: ('a, 'b) = props.x + let q: 'a = props.q + [fst(x), q] +} let make = { let \"Newtype" = (props: props<_>) => make(props) @@ -89,7 +108,10 @@ module Uncurried = { @res.jsxComponentProps type props<'foo> = {foo?: 'foo} - let make = (type a, {?foo, _}: props<_>) => React.null + let make = (type a, props: props<_>) => { + let foo = props.foo + React.null + } let make = { let \"Newtype$Uncurried" = (props: props<_>) => make(props) diff --git a/tests/syntax_tests/data/ppx/react/expected/optimizeAutomaticMode.res.txt b/tests/syntax_tests/data/ppx/react/expected/optimizeAutomaticMode.res.txt index 4dbaf2e084..c374a7815a 100644 --- a/tests/syntax_tests/data/ppx/react/expected/optimizeAutomaticMode.res.txt +++ b/tests/syntax_tests/data/ppx/react/expected/optimizeAutomaticMode.res.txt @@ -7,8 +7,14 @@ module User = { @res.jsxComponentProps type props<'doctor> = {doctor: 'doctor} - let make = ({doctor, _}: props<_>) => { - ReactDOM.jsx("h1", {id: "h1", children: ?ReactDOM.someElement({React.string(format(doctor))})}) + let make = (props: props<_>) => { + let doctor = props.doctor + { + ReactDOM.jsx( + "h1", + {id: "h1", children: ?ReactDOM.someElement({React.string(format(doctor))})}, + ) + } } let make = { let \"OptimizeAutomaticMode$User" = (props: props<_>) => make(props) diff --git a/tests/syntax_tests/data/ppx/react/expected/removedKeyProp.res.txt b/tests/syntax_tests/data/ppx/react/expected/removedKeyProp.res.txt index b2f3551db3..f036784870 100644 --- a/tests/syntax_tests/data/ppx/react/expected/removedKeyProp.res.txt +++ b/tests/syntax_tests/data/ppx/react/expected/removedKeyProp.res.txt @@ -4,7 +4,11 @@ module Foo = { @res.jsxComponentProps type props<'x, 'y> = {x: 'x, y: 'y} - let make = ({x, y, _}: props<_, _>) => React.string(x ++ y) + let make = (props: props<_, _>) => { + let x = props.x + let y = props.y + React.string(x ++ y) + } let make = { let \"RemovedKeyProp$Foo" = (props: props<_>) => make(props) @@ -16,7 +20,10 @@ module HasChildren = { @res.jsxComponentProps type props<'children> = {children: 'children} - let make = ({children, _}: props<_>) => React.createElement(React.fragment, {children: children}) + let make = (props: props<_>) => { + let children = props.children + React.createElement(React.fragment, {children: children}) + } let make = { let \"RemovedKeyProp$HasChildren" = (props: props<_>) => make(props) diff --git a/tests/syntax_tests/data/ppx/react/expected/sharedProps.res.txt b/tests/syntax_tests/data/ppx/react/expected/sharedProps.res.txt index c200b5ba3a..580406d076 100644 --- a/tests/syntax_tests/data/ppx/react/expected/sharedProps.res.txt +++ b/tests/syntax_tests/data/ppx/react/expected/sharedProps.res.txt @@ -3,7 +3,11 @@ module V4C1 = { type props = sharedProps - let make = ({x, y, _}: props) => React.string(x ++ y) + let make = (props: props) => { + let x = props.x + let y = props.y + React.string(x ++ y) + } let make = { let \"SharedProps$V4C1" = props => make(props) @@ -14,7 +18,11 @@ module V4C1 = { module V4C2 = { type props<'a> = sharedProps<'a> - let make = ({x, y, _}: props<_>) => React.string(x ++ y) + let make = (props: props<_>) => { + let x = props.x + let y = props.y + React.string(x ++ y) + } let make = { let \"SharedProps$V4C2" = (props: props<_>) => make(props) @@ -25,7 +33,11 @@ module V4C2 = { module V4C3 = { type props<'a> = sharedProps - let make = ({x, y, _}: props<_>) => React.string(x ++ y) + let make = (props: props<_>) => { + let x = props.x + let y = props.y + React.string(x ++ y) + } let make = { let \"SharedProps$V4C3" = (props: props<_>) => make(props) @@ -36,7 +48,11 @@ module V4C3 = { module V4C4 = { type props = sharedProps - let make = ({x, y, _}: props) => React.string(x ++ y) + let make = (props: props) => { + let x = props.x + let y = props.y + React.string(x ++ y) + } let make = { let \"SharedProps$V4C4" = props => make(props) @@ -68,12 +84,31 @@ module V4C8 = { external make: React.componentLike = "default" } +module V4C9 = { + type props = sharedProps + + let make = (props: props) => { + let x: string = props.x + let y: int = props.y + React.string(x ++ y) + } + let make = { + let \"SharedProps$V4C9" = props => make(props) + + \"SharedProps$V4C9" + } +} + @@jsxConfig({version: 4, mode: "automatic"}) module V4A1 = { type props = sharedProps - let make = ({x, y, _}: props) => React.string(x ++ y) + let make = (props: props) => { + let x = props.x + let y = props.y + React.string(x ++ y) + } let make = { let \"SharedProps$V4A1" = props => make(props) @@ -84,7 +119,11 @@ module V4A1 = { module V4A2 = { type props<'a> = sharedProps<'a> - let make = ({x, y, _}: props<_>) => React.string(x ++ y) + let make = (props: props<_>) => { + let x = props.x + let y = props.y + React.string(x ++ y) + } let make = { let \"SharedProps$V4A2" = (props: props<_>) => make(props) @@ -95,7 +134,11 @@ module V4A2 = { module V4A3 = { type props<'a> = sharedProps - let make = ({x, y, _}: props<_>) => React.string(x ++ y) + let make = (props: props<_>) => { + let x = props.x + let y = props.y + React.string(x ++ y) + } let make = { let \"SharedProps$V4A3" = (props: props<_>) => make(props) @@ -106,7 +149,11 @@ module V4A3 = { module V4A4 = { type props = sharedProps - let make = ({x, y, _}: props) => React.string(x ++ y) + let make = (props: props) => { + let x = props.x + let y = props.y + React.string(x ++ y) + } let make = { let \"SharedProps$V4A4" = props => make(props) @@ -137,3 +184,18 @@ module V4A8 = { external make: React.componentLike = "default" } + +module V4A9 = { + type props = sharedProps + + let make = (props: props) => { + let x: string = props.x + let y: int = props.y + React.string(x ++ y) + } + let make = { + let \"SharedProps$V4A9" = props => make(props) + + \"SharedProps$V4A9" + } +} diff --git a/tests/syntax_tests/data/ppx/react/expected/topLevel.res.txt b/tests/syntax_tests/data/ppx/react/expected/topLevel.res.txt index 8e50d91632..26888d257c 100644 --- a/tests/syntax_tests/data/ppx/react/expected/topLevel.res.txt +++ b/tests/syntax_tests/data/ppx/react/expected/topLevel.res.txt @@ -4,7 +4,9 @@ module V4C = { @res.jsxComponentProps type props<'a, 'b> = {a: 'a, b: 'b} - let make = ({a, b, _}: props<_, _>) => { + let make = (props: props<_, _>) => { + let a = props.a + let b = props.b Js.log("This function should be named 'TopLevel.react'") ReactDOM.createDOMElementVariadic("div", []) } @@ -21,7 +23,9 @@ module V4A = { @res.jsxComponentProps type props<'a, 'b> = {a: 'a, b: 'b} - let make = ({a, b, _}: props<_, _>) => { + let make = (props: props<_, _>) => { + let a = props.a + let b = props.b Js.log("This function should be named 'TopLevel.react'") ReactDOM.jsx("div", {}) } diff --git a/tests/syntax_tests/data/ppx/react/expected/uncurriedProps.res.txt b/tests/syntax_tests/data/ppx/react/expected/uncurriedProps.res.txt index 28da95c83e..919d0a380d 100644 --- a/tests/syntax_tests/data/ppx/react/expected/uncurriedProps.res.txt +++ b/tests/syntax_tests/data/ppx/react/expected/uncurriedProps.res.txt @@ -2,7 +2,8 @@ @res.jsxComponentProps type props<'a> = {a?: 'a} -let make = ({a: ?__a, _}: props unit>) => { +let make = (props: props unit>) => { + let __a: unit => unit = props.a let a = switch __a { | Some(a) => a | None => () => () @@ -30,7 +31,8 @@ module Foo = { @res.jsxComponentProps type props<'callback> = {callback?: 'callback} - let make = ({callback: ?__callback, _}: props<(string, bool, bool) => unit>) => { + let make = (props: props<(string, bool, bool) => unit>) => { + let __callback: (string, bool, bool) => unit = props.callback let callback = switch __callback { | Some(callback) => callback | None => (_, _, _) => () diff --git a/tests/syntax_tests/data/ppx/react/expected/v4.res.txt b/tests/syntax_tests/data/ppx/react/expected/v4.res.txt index 001501391f..67e0ef4bf6 100644 --- a/tests/syntax_tests/data/ppx/react/expected/v4.res.txt +++ b/tests/syntax_tests/data/ppx/react/expected/v4.res.txt @@ -1,6 +1,10 @@ @res.jsxComponentProps type props<'x, 'y> = {x: 'x, y: 'y} // Component with type constraint -let make = ({x, y, _}: props) => React.string(x ++ y) +let make = (props: props) => { + let x: string = props.x + let y: string = props.y + React.string(x ++ y) +} let make = { let \"V4" = (props: props<_>) => make(props) \"V4" @@ -11,7 +15,10 @@ module AnotherName = { type // Component with another name than "make" props<'x> = {x: 'x} - let anotherName = ({x, _}: props<_>) => React.string(x) + let anotherName = (props: props<_>) => { + let x = props.x + React.string(x) + } let anotherName = { let \"V4$AnotherName$anotherName" = (props: props<_>) => anotherName(props) @@ -23,7 +30,10 @@ module Uncurried = { @res.jsxComponentProps type props<'x> = {x: 'x} - let make = ({x, _}: props<_>) => React.string(x) + let make = (props: props<_>) => { + let x = props.x + React.string(x) + } let make = { let \"V4$Uncurried" = (props: props<_>) => make(props) diff --git a/tests/syntax_tests/data/ppx/react/firstClassModules.res b/tests/syntax_tests/data/ppx/react/firstClassModules.res index e1c98d8ca1..d77625b0dc 100644 --- a/tests/syntax_tests/data/ppx/react/firstClassModules.res +++ b/tests/syntax_tests/data/ppx/react/firstClassModules.res @@ -19,6 +19,17 @@ module Select = { } } +module C6 = { + module type Comp = { + let xx: int + @react.component + let make: unit => React.element + } + + @react.component + let make = (~comp as module(Comp: Comp), ~x as (a, b)) => Comp.xx +} + module External = { module type T = { type key diff --git a/tests/syntax_tests/data/ppx/react/sharedProps.res b/tests/syntax_tests/data/ppx/react/sharedProps.res index 13bcf0ded9..7cb8e79dc0 100644 --- a/tests/syntax_tests/data/ppx/react/sharedProps.res +++ b/tests/syntax_tests/data/ppx/react/sharedProps.res @@ -40,6 +40,11 @@ module V4C8 = { external make: (~x: string, ~y: string) => React.element = "default" } +module V4C9 = { + @react.component(:sharedProps) + let make = (~x: string, ~y: int) => React.string(x ++ y) +} + @@jsxConfig({version:4, mode: "automatic"}) module V4A1 = { @@ -80,4 +85,9 @@ module V4A7 = { module V4A8 = { @react.component(:sharedProps) external make: (~x: string, ~y: string) => React.element = "default" +} + +module V4A9 = { + @react.component(:sharedProps) + let make = (~x: string, ~y: int) => React.string(x ++ y) } \ No newline at end of file diff --git a/tests/tests/src/alias_default_value_test.mjs b/tests/tests/src/alias_default_value_test.mjs index ba7e994132..dd62283225 100644 --- a/tests/tests/src/alias_default_value_test.mjs +++ b/tests/tests/src/alias_default_value_test.mjs @@ -2,8 +2,8 @@ function Alias_default_value_test$C0(props) { - let __b = props.b; let __a = props.a; + let __b = props.b; let a = __a !== undefined ? __a : 2; let b = __b !== undefined ? __b : (a << 1); return a + b | 0; @@ -27,11 +27,12 @@ let C1 = { }; function Alias_default_value_test$C2(props) { - let __a = props.a; let __bar = props.foo; + let __a = props.a; + let b = props.b; let bar = __bar !== undefined ? __bar : ""; let a = __a !== undefined ? __a : bar; - return bar + a + props.b; + return bar + a + b; } let C2 = { diff --git a/tests/tests/src/recursive_react_component.mjs b/tests/tests/src/recursive_react_component.mjs index 554e87ec77..c28d3d6923 100644 --- a/tests/tests/src/recursive_react_component.mjs +++ b/tests/tests/src/recursive_react_component.mjs @@ -3,8 +3,9 @@ import * as React from "react"; function make(props) { + let foo = props.foo; return React.createElement(make, { - foo: props.foo + foo: foo }); }