From 2c1f1c59af1253b306ac30a71f58d15a4d7fec9c Mon Sep 17 00:00:00 2001 From: Shulhi Sapli Date: Sat, 24 Aug 2024 21:41:20 +0800 Subject: [PATCH 1/4] Handle different arity when arrow has as attribute during printing --- jscomp/syntax/src/res_parsetree_viewer.ml | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/jscomp/syntax/src/res_parsetree_viewer.ml b/jscomp/syntax/src/res_parsetree_viewer.ml index 75d0228442..f743e82b16 100644 --- a/jscomp/syntax/src/res_parsetree_viewer.ml +++ b/jscomp/syntax/src/res_parsetree_viewer.ml @@ -1,9 +1,17 @@ open Parsetree let arrow_type ?(arity = max_int) ct = + let has_as attrs = + Ext_list.exists attrs (fun (x, _) -> x.Asttypes.txt = "as") + in + let is_any ctyp = + match ctyp with + | {ptyp_desc = Ptyp_any} -> true + | _ -> false + 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 = []; @@ -24,9 +32,15 @@ let arrow_type ?(arity = max_int) ct = | { ptyp_desc = Ptyp_arrow (((Labelled _ | Optional _) as lbl), typ1, typ2); ptyp_attributes = attrs; - } -> - let arg = (attrs, lbl, typ1) in - process attrs_before (arg :: acc) typ2 (arity - 1) + } -> ( + match typ1 with + | {ptyp_desc = Ptyp_any; ptyp_attributes = attrs1} when has_as attrs1 -> + let arg = (attrs, lbl, typ1) in + let arity = if is_any typ2 then arity - 1 else arity in + process attrs_before (arg :: acc) typ2 arity + | _ -> + let arg = (attrs, lbl, typ1) in + process attrs_before (arg :: acc) typ2 (arity - 1)) | typ -> (attrs_before, List.rev acc, typ) in match ct with From a7b4c973db289ebb0fb4a4786b7e232fa428fa16 Mon Sep 17 00:00:00 2001 From: Shulhi Sapli Date: Sat, 24 Aug 2024 21:53:53 +0800 Subject: [PATCH 2/4] Small cleanup --- jscomp/syntax/src/res_parsetree_viewer.ml | 31 ++++++++++++----------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/jscomp/syntax/src/res_parsetree_viewer.ml b/jscomp/syntax/src/res_parsetree_viewer.ml index f743e82b16..bfef73dc8d 100644 --- a/jscomp/syntax/src/res_parsetree_viewer.ml +++ b/jscomp/syntax/src/res_parsetree_viewer.ml @@ -1,14 +1,9 @@ open Parsetree let arrow_type ?(arity = max_int) ct = - let has_as attrs = + let has_as_attr attrs = Ext_list.exists attrs (fun (x, _) -> x.Asttypes.txt = "as") in - let is_any ctyp = - match ctyp with - | {ptyp_desc = Ptyp_any} -> true - | _ -> false - in let rec process attrs_before acc typ arity = match typ with | typ when arity < 0 -> (attrs_before, List.rev acc, typ) @@ -32,15 +27,21 @@ let arrow_type ?(arity = max_int) ct = | { ptyp_desc = Ptyp_arrow (((Labelled _ | Optional _) as lbl), typ1, typ2); ptyp_attributes = attrs; - } -> ( - match typ1 with - | {ptyp_desc = Ptyp_any; ptyp_attributes = attrs1} when has_as attrs1 -> - let arg = (attrs, lbl, typ1) in - let arity = if is_any typ2 then arity - 1 else arity in - process attrs_before (arg :: acc) typ2 arity - | _ -> - let arg = (attrs, lbl, typ1) in - process attrs_before (arg :: acc) typ2 (arity - 1)) + } -> + (* 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 | typ -> (attrs_before, List.rev acc, typ) in match ct with From 24afb1b4a93d6ac1f99daeba52f1540ca65c4ea1 Mon Sep 17 00:00:00 2001 From: Shulhi Sapli Date: Sun, 25 Aug 2024 06:04:06 +0800 Subject: [PATCH 3/4] Add tests --- .../syntax/tests/printer/other/attributes.res | 27 +++++++++++++++++++ .../printer/other/expected/attributes.res.txt | 15 +++++++++++ 2 files changed, 42 insertions(+) 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) _) => _ = "" From 29b07c7de71dcbd39e4781ca5ddb79f996b304f9 Mon Sep 17 00:00:00 2001 From: Shulhi Sapli Date: Sun, 25 Aug 2024 06:06:49 +0800 Subject: [PATCH 4/4] Update CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) 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