From 721aeafc45b6fb9e2e0d1249c9c44fb4fe6f109c Mon Sep 17 00:00:00 2001 From: glennsl Date: Sat, 7 May 2022 11:04:29 +0200 Subject: [PATCH 1/2] jsx: allow locally abstract types in @react.component definitions --- src/reactjs_jsx_ppx_v3.ml | 2 ++ tests/ppx/react/expected/newtype.res.txt | 6 ++++++ tests/ppx/react/newtype.res | 2 ++ 3 files changed, 10 insertions(+) create mode 100644 tests/ppx/react/expected/newtype.res.txt create mode 100644 tests/ppx/react/newtype.res diff --git a/src/reactjs_jsx_ppx_v3.ml b/src/reactjs_jsx_ppx_v3.ml index 628855db..599be71f 100644 --- a/src/reactjs_jsx_ppx_v3.ml +++ b/src/reactjs_jsx_ppx_v3.ml @@ -506,6 +506,8 @@ let jsxMapper () = spelunkForFunExpression innerFunctionExpression | { pexp_desc = Pexp_sequence (_wrapperExpression, innerFunctionExpression) } -> spelunkForFunExpression innerFunctionExpression + | { pexp_desc = Pexp_newtype (_label, innerFunctionExpression) } -> + spelunkForFunExpression innerFunctionExpression | _ -> raise (Invalid_argument diff --git a/tests/ppx/react/expected/newtype.res.txt b/tests/ppx/react/expected/newtype.res.txt new file mode 100644 index 00000000..ffb21c13 --- /dev/null +++ b/tests/ppx/react/expected/newtype.res.txt @@ -0,0 +1,6 @@ +@obj external makeProps: (~a: a, ~b: 'b, ~key: string=?, unit) => {"a": a, "b": 'b} = "" +let make = (type a, ~a: a, ~b, _) => ReactDOMRe.createDOMElementVariadic("div", []) +let make = { + let \"Newtype" = (\"Props": {"a": a, "b": 'b}) => make(~b=\"Props"["b"], ~a=\"Props"["a"]) + \"Newtype" +} diff --git a/tests/ppx/react/newtype.res b/tests/ppx/react/newtype.res new file mode 100644 index 00000000..23e4d4a1 --- /dev/null +++ b/tests/ppx/react/newtype.res @@ -0,0 +1,2 @@ +@react.component +let make = (type a, ~a: a, ~b, _) =>
From 0642aa981098b4c2daa67fd56cdb38c8f7af62d9 Mon Sep 17 00:00:00 2001 From: glennsl Date: Sat, 7 May 2022 11:16:59 +0200 Subject: [PATCH 2/2] jsx: allow type constraints on @react.componenet definitions --- src/reactjs_jsx_ppx_v3.ml | 9 ++++++--- tests/ppx/react/expected/typeConstraint.res.txt | 8 ++++++++ tests/ppx/react/typeConstraint.res | 2 ++ 3 files changed, 16 insertions(+), 3 deletions(-) create mode 100644 tests/ppx/react/expected/typeConstraint.res.txt create mode 100644 tests/ppx/react/typeConstraint.res diff --git a/src/reactjs_jsx_ppx_v3.ml b/src/reactjs_jsx_ppx_v3.ml index 599be71f..10a7f28d 100644 --- a/src/reactjs_jsx_ppx_v3.ml +++ b/src/reactjs_jsx_ppx_v3.ml @@ -93,9 +93,10 @@ let otherAttrsPure (loc, _) = loc.txt <> "react.component" let hasAttrOnBinding { pvb_attributes } = find_opt hasAttr pvb_attributes <> None (* Finds the name of the variable the binding is assigned to, otherwise raises Invalid_argument *) -let getFnName binding = +let rec getFnName binding = match binding with - | { pvb_pat = { ppat_desc = Ppat_var { txt } } } -> txt + | { ppat_desc = Ppat_var { txt } } -> txt + | { ppat_desc = Ppat_constraint (pat, _) } -> getFnName pat | _ -> raise (Invalid_argument "react.component calls cannot be destructured.") [@@raises Invalid_argument] @@ -487,7 +488,7 @@ let jsxMapper () = let bindingLoc = binding.pvb_loc in let bindingPatLoc = binding.pvb_pat.ppat_loc in let binding = { binding with pvb_pat = { binding.pvb_pat with ppat_loc = emptyLoc }; pvb_loc = emptyLoc } in - let fnName = getFnName binding in + let fnName = getFnName binding.pvb_pat in let internalFnName = fnName ^ "$Internal" in let fullModuleName = makeModuleName fileName !nestedModules fnName in let modifiedBindingOld binding = @@ -508,6 +509,8 @@ let jsxMapper () = spelunkForFunExpression innerFunctionExpression | { pexp_desc = Pexp_newtype (_label, innerFunctionExpression) } -> spelunkForFunExpression innerFunctionExpression + | { pexp_desc = Pexp_constraint (innerFunctionExpression, _typ) } -> + spelunkForFunExpression innerFunctionExpression | _ -> raise (Invalid_argument diff --git a/tests/ppx/react/expected/typeConstraint.res.txt b/tests/ppx/react/expected/typeConstraint.res.txt new file mode 100644 index 00000000..8940b164 --- /dev/null +++ b/tests/ppx/react/expected/typeConstraint.res.txt @@ -0,0 +1,8 @@ +@obj external makeProps: (~a: 'a, ~b: 'b, ~key: string=?, unit) => {"a": 'a, "b": 'b} = "" +let make: + type a. (~a: a, ~b: a, a) => React.element = + (~a, ~b, _) => ReactDOMRe.createDOMElementVariadic("div", []) +let make = { + let \"TypeConstraint" = (\"Props": {"a": 'a, "b": 'b}) => make(~b=\"Props"["b"], ~a=\"Props"["a"]) + \"TypeConstraint" +} diff --git a/tests/ppx/react/typeConstraint.res b/tests/ppx/react/typeConstraint.res new file mode 100644 index 00000000..cbe88490 --- /dev/null +++ b/tests/ppx/react/typeConstraint.res @@ -0,0 +1,2 @@ +@react.component +let make: type a. (~a: a, ~b: a, a) => React.element = (~a, ~b, _) =>