diff --git a/CHANGELOG.md b/CHANGELOG.md index 796a10a892..b880fa4604 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ - Fix issue where long layout break added a trailing comma in partial application `...`. https://github.com/rescript-lang/rescript-compiler/pull/6949 - Fix incorrect format of function under unary operator. https://github.com/rescript-lang/rescript-compiler/pull/6953 - Fix incorrect incorrect printing of module binding with signature. https://github.com/rescript-lang/rescript-compiler/pull/6963 +- Fix incorrect printing of external with `@as` attribute and `_` placholder (fixed argument). https://github.com/rescript-lang/rescript-compiler/pull/6970 #### :house: Internal diff --git a/jscomp/syntax/src/res_parsetree_viewer.ml b/jscomp/syntax/src/res_parsetree_viewer.ml index 75d0228442..bfef73dc8d 100644 --- a/jscomp/syntax/src/res_parsetree_viewer.ml +++ b/jscomp/syntax/src/res_parsetree_viewer.ml @@ -1,9 +1,12 @@ open Parsetree let arrow_type ?(arity = max_int) ct = + let has_as_attr attrs = + Ext_list.exists attrs (fun (x, _) -> x.Asttypes.txt = "as") + in let rec process attrs_before acc typ arity = match typ with - | typ when arity <= 0 -> (attrs_before, List.rev acc, typ) + | typ when arity < 0 -> (attrs_before, List.rev acc, typ) | { ptyp_desc = Ptyp_arrow ((Nolabel as lbl), typ1, typ2); ptyp_attributes = []; @@ -25,8 +28,20 @@ let arrow_type ?(arity = max_int) ct = ptyp_desc = Ptyp_arrow (((Labelled _ | Optional _) as lbl), typ1, typ2); ptyp_attributes = attrs; } -> + (* Res_core.parse_es6_arrow_type has a workaround that removed an extra arity for the function if the + argument is a Ptyp_any with @as attribute i.e. ~x: @as(`{prop: value}`) _. + + When this case is encountered we add that missing arity so the arrow is printed properly. + *) + let arity = + match typ1 with + | {ptyp_desc = Ptyp_any; ptyp_attributes = attrs1} + when has_as_attr attrs1 -> + arity + | _ -> arity - 1 + in let arg = (attrs, lbl, typ1) in - process attrs_before (arg :: acc) typ2 (arity - 1) + process attrs_before (arg :: acc) typ2 arity | typ -> (attrs_before, List.rev acc, typ) in match ct with diff --git a/jscomp/syntax/tests/printer/other/attributes.res b/jscomp/syntax/tests/printer/other/attributes.res index 1df3f38b6c..722518ae22 100644 --- a/jscomp/syntax/tests/printer/other/attributes.res +++ b/jscomp/syntax/tests/printer/other/attributes.res @@ -24,3 +24,30 @@ let x = 1 ) let x = 1 +@obj external ff: (~x: int, ~g: int, ~h: int) => _ = "" + +@obj external ff: (~x: int, ~g: int, ~h: @as(3) _) => _ = "" + +@obj external ff: (~x: int) => (~h: @as(3) _) => _ = "" + +@obj +external ff: ( + ~lo: @as(3) _, + ~mid: @as(3) _, + ~hi: int, +) => _ = "" + + +@obj +external ff: ( + ~hi: int, + ~lo: @as(3) _ +) => _ = "" + +@obj +external ff: ( + ~hi: int, + ~mid: @as(3) _, + ~lo: @as(3) _ +) => _ = "" + diff --git a/jscomp/syntax/tests/printer/other/expected/attributes.res.txt b/jscomp/syntax/tests/printer/other/expected/attributes.res.txt index 5f353627ef..b34daf6830 100644 --- a/jscomp/syntax/tests/printer/other/expected/attributes.res.txt +++ b/jscomp/syntax/tests/printer/other/expected/attributes.res.txt @@ -22,3 +22,18 @@ let x = 1 @inlinePrivate(@module("./logo.svg") external logo: string = "default") let x = 1 + +@obj external ff: (~x: int, ~g: int, ~h: int) => _ = "" + +@obj external ff: (~x: int, ~g: int, ~h: @as(3) _) => _ = "" + +@obj external ff: (~x: int) => (~h: @as(3) _) => _ = "" + +@obj +external ff: (~lo: @as(3) _, ~mid: @as(3) _, ~hi: int) => _ = "" + +@obj +external ff: (~hi: int, ~lo: @as(3) _) => _ = "" + +@obj +external ff: (~hi: int, ~mid: @as(3) _, ~lo: @as(3) _) => _ = ""