From 555dc05ea2076ae5c20ca523b108902e55070300 Mon Sep 17 00:00:00 2001 From: Woonki Moon Date: Sat, 1 Oct 2022 20:19:04 +0900 Subject: [PATCH 1/6] add first-class-module test --- .../react/expected/firstClassModules.res.txt | 84 +++++++++++++++++++ tests/ppx/react/firstClassModules.res | 41 +++++++++ 2 files changed, 125 insertions(+) create mode 100644 tests/ppx/react/expected/firstClassModules.res.txt create mode 100644 tests/ppx/react/firstClassModules.res diff --git a/tests/ppx/react/expected/firstClassModules.res.txt b/tests/ppx/react/expected/firstClassModules.res.txt new file mode 100644 index 00000000..2cd72ff2 --- /dev/null +++ b/tests/ppx/react/expected/firstClassModules.res.txt @@ -0,0 +1,84 @@ +@@jsxConfig({version: 3}) + +module Select = { + module type T = { + type key + type t + } + @obj + external makeProps: ( + ~model: module(T with type t = '\"type-a" and type key = '\"type-key"), + ~selected: option<'\"type-key">, + ~onChange: option<'\"type-key"> => unit, + ~items: array<'\"type-a">, + ~key: string=?, + unit, + ) => { + "model": module(T with type t = '\"type-a" and type key = '\"type-key"), + "selected": option<'\"type-key">, + "onChange": option<'\"type-key"> => unit, + "items": array<'\"type-a">, + } = "" + + @react.component + let make = ( + type a key, + ~model as module(T: T with type t = a and type key = key), + ~selected: option, + ~onChange: option => unit, + ~items: array, + ) => { + let _ = (model, selected, onChange, items) + ReactDOMRe.createDOMElementVariadic("div", []) + } + let make = { + let \"FirstClassModules$Select" = ( + \"Props": { + "model": module(T with type t = '\"type-a" and type key = '\"type-key"), + "selected": option<'\"type-key">, + "onChange": option<'\"type-key"> => unit, + "items": array<'\"type-a">, + }, + ) => + make( + ~items=\"Props"["items"], + ~onChange=\"Props"["onChange"], + ~selected=\"Props"["selected"], + ~model=\"Props"["model"], + ) + \"FirstClassModules$Select" + } +} + +@@jsxConfig({version: 4, mode: "classic"}) + +module Select = { + module type T = { + type key + type t + } + type props<'model, 'selected, 'onChange, 'items> = { + model: 'model, + selected: 'selected, + onChange: 'onChange, + items: 'items, + } + + @react.component + let make = ( + {model: module(T), selected, onChange, items, _}: props< + module(T with type t = '\"type-a" and type key = '\"type-key"), + option<'\"type-key">, + option<'\"type-key"> => unit, + array<'\"type-a">, + >, + ) => { + let _ = (model, selected, onChange, items) + ReactDOM.createDOMElementVariadic("div", []) + } + let make = { + let \"FirstClassModules$Select" = (props: props<_>) => make(props) + + \"FirstClassModules$Select" + } +} diff --git a/tests/ppx/react/firstClassModules.res b/tests/ppx/react/firstClassModules.res new file mode 100644 index 00000000..8edd75b5 --- /dev/null +++ b/tests/ppx/react/firstClassModules.res @@ -0,0 +1,41 @@ +@@jsxConfig({version: 3}) + +module Select = { + module type T = { + type key + type t + } + + @react.component + let make = ( + type a key, + ~model as module(T: T with type t = a and type key = key), + ~selected: option, + ~onChange: option => unit, + ~items: array, + ) => { + let _ = (model, selected, onChange, items) +
+ } +} + +@@jsxConfig({version: 4, mode: "classic"}) + +module Select = { + module type T = { + type key + type t + } + + @react.component + let make = ( + type a key, + ~model as module(T: T with type t = a and type key = key), + ~selected: option, + ~onChange: option => unit, + ~items: array, + ) => { + let _ = (model, selected, onChange, items) +
+ } +} From ca5a77ea8d73dbb1b84ebc5414aeb3032f2d0171 Mon Sep 17 00:00:00 2001 From: Woonki Moon Date: Sun, 2 Oct 2022 01:24:22 +0900 Subject: [PATCH 2/6] fix jsx v4 for first-class-module --- cli/reactjs_jsx_v4.ml | 12 +++++++++--- tests/ppx/react/expected/firstClassModules.res.txt | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/cli/reactjs_jsx_v4.ml b/cli/reactjs_jsx_v4.ml index a7a016d7..1bab39c4 100644 --- a/cli/reactjs_jsx_v4.ml +++ b/cli/reactjs_jsx_v4.ml @@ -1005,9 +1005,13 @@ let transformStructureItem ~config mapper item = ] (Exp.ident ~loc:pstr_loc {loc = emptyLoc; txt = Lident txt}) in - let stripConstraint pattern = + let rec stripConstraintUnpack ~label pattern = match pattern with - | {ppat_desc = Ppat_constraint (pattern, _)} -> pattern + | {ppat_desc = Ppat_constraint (pattern, _)} -> + stripConstraintUnpack ~label pattern + | {ppat_desc = Ppat_unpack _; ppat_loc} -> + (* remove unback e.g. model: module(T) *) + Pat.var ~loc:ppat_loc {txt = label; loc = ppat_loc} | _ -> pattern in let rec returnedExpression patternsWithLabel patternsWithNolabel @@ -1029,7 +1033,9 @@ let transformStructureItem ~config mapper item = | Pexp_fun (arg_label, _default, ({ppat_loc; ppat_desc} as pattern), expr) -> ( - let patternWithoutConstraint = stripConstraint pattern in + let patternWithoutConstraint = + stripConstraintUnpack ~label:(getLabel arg_label) pattern + in if isLabelled arg_label || isOptional arg_label then returnedExpression (( {loc = ppat_loc; txt = Lident (getLabel arg_label)}, diff --git a/tests/ppx/react/expected/firstClassModules.res.txt b/tests/ppx/react/expected/firstClassModules.res.txt index 2cd72ff2..04585d46 100644 --- a/tests/ppx/react/expected/firstClassModules.res.txt +++ b/tests/ppx/react/expected/firstClassModules.res.txt @@ -66,7 +66,7 @@ module Select = { @react.component let make = ( - {model: module(T), selected, onChange, items, _}: props< + {model, selected, onChange, items, _}: props< module(T with type t = '\"type-a" and type key = '\"type-key"), option<'\"type-key">, option<'\"type-key"> => unit, From 56a3df70f19cd1a08c62ed06b17b7b2a6210d994 Mon Sep 17 00:00:00 2001 From: Woonki Moon Date: Sun, 2 Oct 2022 01:25:34 +0900 Subject: [PATCH 3/6] add test external for first-class-module --- .../react/expected/firstClassModules.res.txt | 24 +++++++++++++++++++ tests/ppx/react/firstClassModules.res | 15 ++++++++++++ 2 files changed, 39 insertions(+) diff --git a/tests/ppx/react/expected/firstClassModules.res.txt b/tests/ppx/react/expected/firstClassModules.res.txt index 04585d46..c55d9e8b 100644 --- a/tests/ppx/react/expected/firstClassModules.res.txt +++ b/tests/ppx/react/expected/firstClassModules.res.txt @@ -82,3 +82,27 @@ module Select = { \"FirstClassModules$Select" } } + +module External = { + module type T = { + type key + type t + } + type props<'model, 'selected, 'onChange, 'items> = { + model: 'model, + selected: 'selected, + onChange: 'onChange, + items: 'items, + } + + @module("c") + external make: React.componentLike< + props< + module(T with type t = 'a and type key = 'key), + option<'key>, + (option<'key> => unit), + array<'a>, + >, + React.element, + > = "default" +} diff --git a/tests/ppx/react/firstClassModules.res b/tests/ppx/react/firstClassModules.res index 8edd75b5..9567f435 100644 --- a/tests/ppx/react/firstClassModules.res +++ b/tests/ppx/react/firstClassModules.res @@ -39,3 +39,18 @@ module Select = {
} } + +module External = { + module type T = { + type key + type t + } + + @react.component @module("c") + external make: ( + ~model: module(T with type t = 'a and type key = 'key), + ~selected: option<'key>, + ~onChange: option<'key> => unit, + ~items: array<'a>, + ) => React.element = "default" +} From 184dedd9104d4b7c5ffbb7ac527c6822cde8b65e Mon Sep 17 00:00:00 2001 From: Woonki Moon Date: Sun, 2 Oct 2022 01:26:15 +0900 Subject: [PATCH 4/6] add test interface of first-class-module --- .../react/expected/firstClassModules.resi.txt | 57 +++++++++++++++++++ tests/ppx/react/firstClassModules.resi | 33 +++++++++++ 2 files changed, 90 insertions(+) create mode 100644 tests/ppx/react/expected/firstClassModules.resi.txt create mode 100644 tests/ppx/react/firstClassModules.resi diff --git a/tests/ppx/react/expected/firstClassModules.resi.txt b/tests/ppx/react/expected/firstClassModules.resi.txt new file mode 100644 index 00000000..e5ec53af --- /dev/null +++ b/tests/ppx/react/expected/firstClassModules.resi.txt @@ -0,0 +1,57 @@ +@@jsxConfig({version: 3}) + +module Select: { + module type T = { + type key + type t + } + + @obj + external makeProps: ( + ~model: module(T with type t = 'a and type key = 'key), + ~selected: option<'key>, + ~onChange: option<'key> => unit, + ~items: array<'a>, + ~key: string=?, + unit, + ) => { + "model": module(T with type t = 'a and type key = 'key), + "selected": option<'key>, + "onChange": (option<'key> => unit), + "items": array<'a>, + } = "" + let make: React.componentLike< + { + "model": module(T with type t = 'a and type key = 'key), + "selected": option<'key>, + "onChange": (option<'key> => unit), + "items": array<'a>, + }, + React.element, + > +} + +@@jsxConfig({version: 4, mode: "classic"}) + +module Select: { + module type T = { + type key + type t + } + type props<'model, 'selected, 'onChange, 'items> = { + model: 'model, + selected: 'selected, + onChange: 'onChange, + items: 'items, + } + + let make: React.componentLike< + props< + module(T with type t = 'a and type key = 'key), + option<'key>, + (option<'key> => unit), + array<'a>, + >, + React.element, + > +} diff --git a/tests/ppx/react/firstClassModules.resi b/tests/ppx/react/firstClassModules.resi new file mode 100644 index 00000000..9f601b3a --- /dev/null +++ b/tests/ppx/react/firstClassModules.resi @@ -0,0 +1,33 @@ +@@jsxConfig({version: 3}) + +module Select: { + module type T = { + type key + type t + } + + @react.component + let make: ( + ~model: module(T with type t = 'a and type key = 'key), + ~selected: option<'key>, + ~onChange: option<'key> => unit, + ~items: array<'a>, + ) => React.element +} + +@@jsxConfig({version: 4, mode: "classic"}) + +module Select: { + module type T = { + type key + type t + } + + @react.component + let make: ( + ~model: module(T with type t = 'a and type key = 'key), + ~selected: option<'key>, + ~onChange: option<'key> => unit, + ~items: array<'a>, + ) => React.element +} From 5c873a449a19d1c881a15efa041f88e622594689 Mon Sep 17 00:00:00 2001 From: Woonki Moon Date: Sun, 2 Oct 2022 01:34:43 +0900 Subject: [PATCH 5/6] fix typo comment --- cli/reactjs_jsx_v4.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/reactjs_jsx_v4.ml b/cli/reactjs_jsx_v4.ml index 1bab39c4..dd77662c 100644 --- a/cli/reactjs_jsx_v4.ml +++ b/cli/reactjs_jsx_v4.ml @@ -1010,7 +1010,7 @@ let transformStructureItem ~config mapper item = | {ppat_desc = Ppat_constraint (pattern, _)} -> stripConstraintUnpack ~label pattern | {ppat_desc = Ppat_unpack _; ppat_loc} -> - (* remove unback e.g. model: module(T) *) + (* remove unpack e.g. model: module(T) *) Pat.var ~loc:ppat_loc {txt = label; loc = ppat_loc} | _ -> pattern in From f285af8d7ce9c2f015d55f0ce435015613c82089 Mon Sep 17 00:00:00 2001 From: Woonki Moon Date: Sun, 2 Oct 2022 17:44:36 +0900 Subject: [PATCH 6/6] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a26e9d35..026e2767 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,6 +33,7 @@ - Fix parsing (hence pretty printing) of expressions with underscore `_` and comments. - Fix printing of comments inside JSX tag https://github.com/rescript-lang/syntax/pull/664 - Fix issue where formatter erases tail comments inside JSX tag https://github.com/rescript-lang/syntax/issues/663 +- Fix issue where the JSX prop has type annotation of the first class module https://github.com/rescript-lang/syntax/pull/666 ## ReScript 10.0