diff --git a/CHANGELOG.md b/CHANGELOG.md index 73ce10beba..6fa0a8475e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/jscomp/frontend/ast_external_process.ml b/jscomp/frontend/ast_external_process.ml index c2137a7502..82a6000029 100644 --- a/jscomp/frontend/ast_external_process.ml +++ b/jscomp/frontend/ast_external_process.ml @@ -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 -> @@ -407,7 +414,7 @@ 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, @@ -415,31 +422,31 @@ let process_obj (loc : Location.t) (st : external_desc) (prim_name : string) 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 ) @@ -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 | 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 -> @@ -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 () ) @@ -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 diff --git a/jscomp/syntax/tests/ppx/react/expected/mangleKeyword.res.txt b/jscomp/syntax/tests/ppx/react/expected/mangleKeyword.res.txt index 5b6ad70b29..087f649aed 100644 --- a/jscomp/syntax/tests/ppx/react/expected/mangleKeyword.res.txt +++ b/jscomp/syntax/tests/ppx/react/expected/mangleKeyword.res.txt @@ -1,21 +1,38 @@ @@jsxConfig({version: 3}) -module C30 = { - @obj external makeProps: (~_open: 'T_open, ~key: string=?, unit) => {"_open": 'T_open} = "" +module C3A0 = { + @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"}) diff --git a/jscomp/syntax/tests/ppx/react/mangleKeyword.res b/jscomp/syntax/tests/ppx/react/mangleKeyword.res index 2e0fa7c344..94dad3c2c0 100644 --- a/jscomp/syntax/tests/ppx/react/mangleKeyword.res +++ b/jscomp/syntax/tests/ppx/react/mangleKeyword.res @@ -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 = -let c31 = +let c3a0 = +let c3a1 = @@jsxConfig({version: 4, mode: "classic"}) diff --git a/jscomp/test/external_ppx.js b/jscomp/test/external_ppx.js index c727881a0f..d7bcc73ac0 100644 --- a/jscomp/test/external_ppx.js +++ b/jscomp/test/external_ppx.js @@ -3,6 +3,17 @@ var External_ppxGen = require("./external_ppx.gen"); +function renamed(param) { + var tmp = { + type: "123", + normal: 12 + }; + if (param !== undefined) { + tmp.WIDTH = param; + } + return tmp; +} + var u = { hi: 2, lo: 3, @@ -15,6 +26,7 @@ function f(prim) { return External_ppxGen.f(prim); } +exports.renamed = renamed; exports.u = u; exports.f = f; /* ./external_ppx.gen Not a pure module */ diff --git a/jscomp/test/external_ppx.res b/jscomp/test/external_ppx.res index 28665f702e..18473997d4 100644 --- a/jscomp/test/external_ppx.res +++ b/jscomp/test/external_ppx.res @@ -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,