Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add @as support for obj ppx #6412

Merged
merged 7 commits into from
Sep 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#### :rocket: New Feature

- Support renaming fields in inline records with `@as` attribute. [#6391](https://github.com/rescript-lang/rescript-compiler/pull/6391)
- Support renaming object fields of `@obj` external ppx with `@as` attribute. [#6391](https://github.com/rescript-lang/rescript-compiler/pull/6412)
- Add builtin abstract types for File and Blob APIs. https://github.com/rescript-lang/rescript-compiler/pull/6383
- Untagged variants: Support `promise`, RegExes, Dates, File and Blob. https://github.com/rescript-lang/rescript-compiler/pull/6383
- Support aliased types as payloads to untagged variants. https://github.com/rescript-lang/rescript-compiler/pull/6394
Expand Down
52 changes: 33 additions & 19 deletions jscomp/frontend/ast_external_process.ml
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,14 @@ let process_obj (loc : Location.t) (st : external_desc) (prim_name : string)
| _ ->
Location.raise_errorf ~loc
"expect label, optional, or unit here")
| Labelled name -> (
| Labelled label -> (
let fieldName =
match
Ast_attributes.iter_process_bs_string_as param_type.attr
with
| Some alias -> alias
| None -> label
in
let obj_arg_type = refine_obj_arg_type ~nolabel:false ty in
match obj_arg_type with
| Ignore ->
Expand All @@ -407,39 +414,39 @@ let process_obj (loc : Location.t) (st : external_desc) (prim_name : string)
result_types )
| Arg_cst _ ->
( {
obj_arg_label = External_arg_spec.obj_label name;
obj_arg_label = External_arg_spec.obj_label fieldName;
obj_arg_type;
},
arg_types,
(* ignored in [arg_types], reserved in [result_types] *)
result_types )
| Nothing ->
( {
obj_arg_label = External_arg_spec.obj_label name;
obj_arg_label = External_arg_spec.obj_label fieldName;
obj_arg_type;
},
param_type :: arg_types,
Parsetree.Otag ({Asttypes.txt = name; loc}, [], ty)
Parsetree.Otag ({Asttypes.txt = fieldName; loc}, [], ty)
:: result_types )
| Int _ ->
( {
obj_arg_label = External_arg_spec.obj_label name;
obj_arg_label = External_arg_spec.obj_label fieldName;
obj_arg_type;
},
param_type :: arg_types,
Otag
( {Asttypes.txt = name; loc},
( {Asttypes.txt = fieldName; loc},
[],
Ast_literal.type_int ~loc () )
:: result_types )
| Poly_var_string _ ->
( {
obj_arg_label = External_arg_spec.obj_label name;
obj_arg_label = External_arg_spec.obj_label fieldName;
obj_arg_type;
},
param_type :: arg_types,
Otag
( {Asttypes.txt = name; loc},
( {Asttypes.txt = fieldName; loc},
[],
Ast_literal.type_string ~loc () )
:: result_types )
Expand All @@ -449,11 +456,18 @@ let process_obj (loc : Location.t) (st : external_desc) (prim_name : string)
| Extern_unit -> assert false
| Poly_var _ ->
Location.raise_errorf ~loc
"%@obj label %s does not support such arg type" name
"%@obj label %s does not support such arg type" label
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Separate from this PR, but these errors would be good to clean up too at some point.

| Unwrap ->
Location.raise_errorf ~loc
"%@obj label %s does not support %@unwrap arguments" name)
| Optional name -> (
"%@obj label %s does not support %@unwrap arguments" label)
| Optional label -> (
let fieldName =
match
Ast_attributes.iter_process_bs_string_as param_type.attr
with
| Some alias -> alias
| None -> label
in
let obj_arg_type = get_opt_arg_type ~nolabel:false ty in
match obj_arg_type with
| Ignore ->
Expand All @@ -469,35 +483,35 @@ let process_obj (loc : Location.t) (st : external_desc) (prim_name : string)
in
( {
obj_arg_label =
External_arg_spec.optional for_sure_not_nested name;
External_arg_spec.optional for_sure_not_nested fieldName;
obj_arg_type;
},
param_type :: arg_types,
Parsetree.Otag
( {Asttypes.txt = name; loc},
( {Asttypes.txt = fieldName; loc},
[],
Ast_comb.to_undefined_type loc ty )
:: result_types )
| Int _ ->
( {
obj_arg_label = External_arg_spec.optional true name;
obj_arg_label = External_arg_spec.optional true fieldName;
obj_arg_type;
},
param_type :: arg_types,
Otag
( {Asttypes.txt = name; loc},
( {Asttypes.txt = fieldName; loc},
[],
Ast_comb.to_undefined_type loc
@@ Ast_literal.type_int ~loc () )
:: result_types )
| Poly_var_string _ ->
( {
obj_arg_label = External_arg_spec.optional true name;
obj_arg_label = External_arg_spec.optional true fieldName;
obj_arg_type;
},
param_type :: arg_types,
Otag
( {Asttypes.txt = name; loc},
( {Asttypes.txt = fieldName; loc},
[],
Ast_comb.to_undefined_type loc
@@ Ast_literal.type_string ~loc () )
Expand All @@ -511,10 +525,10 @@ let process_obj (loc : Location.t) (st : external_desc) (prim_name : string)
| Extern_unit -> assert false
| Poly_var _ ->
Location.raise_errorf ~loc
"%@obj label %s does not support such arg type" name
"%@obj label %s does not support such arg type" label
| Unwrap ->
Location.raise_errorf ~loc
"%@obj label %s does not support %@unwrap arguments" name)
"%@obj label %s does not support %@unwrap arguments" label)
in
(new_arg_label :: arg_labels, new_arg_types, output_tys))
in
Expand Down
37 changes: 27 additions & 10 deletions jscomp/syntax/tests/ppx/react/expected/mangleKeyword.res.txt
Original file line number Diff line number Diff line change
@@ -1,21 +1,38 @@
@@jsxConfig({version: 3})

module C30 = {
@obj external makeProps: (~_open: 'T_open, ~key: string=?, unit) => {"_open": 'T_open} = ""
module C3A0 = {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not affected in the PR

@obj
external makeProps: (
~_open: 'T_open,
~_type: string,
~key: string=?,
unit,
) => {"_open": 'T_open, "_type": string} = ""

@react.component let make = @warning("-16") (~_open) => React.string(_open)
@react.component
let make =
@warning("-16")
(@as("open") ~_open) => @warning("-16") (@as("type") ~_type: string) => React.string(_open)
let make = {
let \"MangleKeyword$C30" = (\"Props": {"_open": 'T_open}) => make(~_open=\"Props"["_open"])
\"MangleKeyword$C30"
let \"MangleKeyword$C3A0" = (\"Props": {"_open": 'T_open, "_type": string}) =>
make(~_type=\"Props"["_type"], ~_open=\"Props"["_open"])
\"MangleKeyword$C3A0"
}
}
module C31 = {
@obj external makeProps: (~_open: string, ~key: string=?, unit) => {"_open": string} = ""
external make: React.componentLike<{"_open": string}, React.element> = "default"
module C3A1 = {
@obj
external makeProps: (
~_open: string,
~_type: string,
~key: string=?,
unit,
) => {"_open": string, "_type": string} = ""
external make: @as("open")
React.componentLike<{"_open": string, "_type": string}, React.element> = "default"
}

let c30 = React.createElement(C30.make, C30.makeProps(~_open="x", ()))
let c31 = React.createElement(C31.make, C31.makeProps(~_open="x", ()))
let c3a0 = React.createElement(C3A0.make, C3A0.makeProps(~_open="x", ~_type="t", ()))
let c3a1 = React.createElement(C3A1.make, C3A1.makeProps(~_open="x", ~_type="t", ()))

@@jsxConfig({version: 4, mode: "classic"})

Expand Down
14 changes: 8 additions & 6 deletions jscomp/syntax/tests/ppx/react/mangleKeyword.res
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
@@jsxConfig({version: 3})

module C30 = {
module C3A0 = {
@react.component
let make = (~_open) => React.string(_open)
let make =
(@as("open") ~_open, @as("type") ~_type: string) => React.string(_open)
}
module C31 = {
module C3A1 = {
@react.component
external make: (~_open: string) => React.element = "default"
external make: (@as("open") ~_open: string, @as("type") ~_type: string) => React.element =
"default"
}

let c30 = <C30 _open="x" />
let c31 = <C31 _open="x" />
let c3a0 = <C3A0 _open="x" _type="t" />
let c3a1 = <C3A1 _open="x" _type="t" />

@@jsxConfig({version: 4, mode: "classic"})

Expand Down
12 changes: 12 additions & 0 deletions jscomp/test/external_ppx.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions jscomp/test/external_ppx.res
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,15 @@ external make_config: (~length: 'a, ~width: int) => unit = ""

@obj external opt_make: (~length: int, ~width: int=?) => (_ as 'event) = ""

@obj
external renamed_make: (
@as("type") ~_type: string,
@as("WIDTH") ~width: int=?,
~normal: float,
) => (_ as 'event) = ""

let renamed = renamed_make(~_type="123", ~normal=12.)

@obj
external ff: (
~hi: int,
Expand Down