From a9b843ecd8bccd58a38253d86caf5f3a46b13528 Mon Sep 17 00:00:00 2001 From: Cristiano Calcagno Date: Fri, 14 Oct 2022 14:23:16 +0100 Subject: [PATCH 1/6] More async examples. See https://github.com/rescript-lang/syntax/issues/679 --- tests/printer/expr/asyncAwait.res | 5 +++++ tests/printer/expr/expected/asyncAwait.res.txt | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/tests/printer/expr/asyncAwait.res b/tests/printer/expr/asyncAwait.res index 962cfa91..a88c1031 100644 --- a/tests/printer/expr/asyncAwait.res +++ b/tests/printer/expr/asyncAwait.res @@ -85,3 +85,8 @@ let _ = await { let f = async (~x, ~y) => x + y let f = async (@foo ~x, @bar ~y) => x + y let f = @foo async ( @bar ~x as @zz z, ~y) => x + y +let f = async x => x +let f = async x => async y => 3 +let f = async (~x) => async y => 3 +let f = async x => async (~y) => 3 +let f = async (~x) => async (~y) => 3 diff --git a/tests/printer/expr/expected/asyncAwait.res.txt b/tests/printer/expr/expected/asyncAwait.res.txt index c4b56323..effe5392 100644 --- a/tests/printer/expr/expected/asyncAwait.res.txt +++ b/tests/printer/expr/expected/asyncAwait.res.txt @@ -107,3 +107,8 @@ let _ = await { let f = async (~x, ~y) => x + y let f = async (@foo ~x, @bar ~y) => x + y let f = async (@bar @foo ~x as @zz z, ~y) => x + y +let f = async (x) => x +let f = async (x) => async (y) => 3 +let f = async (~x) => async (y) => 3 +let f = async (x, ~y) => 3 +let f = async (~x, ~y) => 3 From 58a07baca73dadfefc1b599ed879d36c100f5243 Mon Sep 17 00:00:00 2001 From: Cristiano Calcagno Date: Fri, 14 Oct 2022 14:42:03 +0100 Subject: [PATCH 2/6] Even more examples. --- tests/printer/expr/asyncAwait.res | 2 ++ tests/printer/expr/expected/asyncAwait.res.txt | 2 ++ 2 files changed, 4 insertions(+) diff --git a/tests/printer/expr/asyncAwait.res b/tests/printer/expr/asyncAwait.res index a88c1031..7ef4f51e 100644 --- a/tests/printer/expr/asyncAwait.res +++ b/tests/printer/expr/asyncAwait.res @@ -90,3 +90,5 @@ let f = async x => async y => 3 let f = async (~x) => async y => 3 let f = async x => async (~y) => 3 let f = async (~x) => async (~y) => 3 +let f = x => async (~y) => 3 +let f = x => async y => 3 diff --git a/tests/printer/expr/expected/asyncAwait.res.txt b/tests/printer/expr/expected/asyncAwait.res.txt index effe5392..4d648082 100644 --- a/tests/printer/expr/expected/asyncAwait.res.txt +++ b/tests/printer/expr/expected/asyncAwait.res.txt @@ -112,3 +112,5 @@ let f = async (x) => async (y) => 3 let f = async (~x) => async (y) => 3 let f = async (x, ~y) => 3 let f = async (~x, ~y) => 3 +let f = async (x, ~y) => 3 +let f = x => async (y) => 3 From 66a258a81affbf340af3339a741043c440f5165c Mon Sep 17 00:00:00 2001 From: Cristiano Calcagno Date: Fri, 14 Oct 2022 15:45:45 +0100 Subject: [PATCH 3/6] Fix a bunch of async printing issues including an infinite loop. The infinite loop happens when the expression is returned unchanged. Now checking that some progress is made. Fixes https://github.com/rescript-lang/syntax/issues/681 --- src/res_parsetree_viewer.ml | 20 +++++++++++------- tests/printer/expr/asyncAwait.res | 21 ++++++++++--------- .../printer/expr/expected/asyncAwait.res.txt | 21 ++++++++++--------- tests/printer/expr/expected/fun.res.txt | 2 +- 4 files changed, 35 insertions(+), 29 deletions(-) diff --git a/src/res_parsetree_viewer.ml b/src/res_parsetree_viewer.ml index d728d687..8ab7b31e 100644 --- a/src/res_parsetree_viewer.ml +++ b/src/res_parsetree_viewer.ml @@ -136,7 +136,7 @@ let funExpr expr = collectNewTypes (stringLoc :: acc) returnExpr | returnExpr -> (List.rev acc, returnExpr) in - let rec collect attrsBefore acc expr = + let rec collect n attrsBefore acc expr = match expr with | { pexp_desc = @@ -152,13 +152,17 @@ let funExpr expr = pexp_attributes = []; } -> let parameter = Parameter {attrs = []; lbl; defaultExpr; pat = pattern} in - collect attrsBefore (parameter :: acc) returnExpr + collect (n + 1) attrsBefore (parameter :: acc) returnExpr | {pexp_desc = Pexp_newtype (stringLoc, rest); pexp_attributes = attrs} -> let stringLocs, returnExpr = collectNewTypes [stringLoc] rest in let param = NewTypes {attrs; locs = stringLocs} in - collect attrsBefore (param :: acc) returnExpr - | {pexp_desc = Pexp_fun _; pexp_attributes = [({txt = "bs"}, _)]} -> - (* stop here, the uncurried attribute always indicates the beginning of an arrow function + collect (n + 1) attrsBefore (param :: acc) returnExpr + | {pexp_desc = Pexp_fun _; pexp_attributes} + when pexp_attributes + |> List.exists (fun ({Location.txt}, _) -> + txt = "bs" || txt = "res.async") + && n > 0 -> + (* stop here, the uncurried or async attribute always indicates the beginning of an arrow function * e.g. `(. a) => (. b)` instead of `(. a, . b)` *) (attrsBefore, List.rev acc, expr) | { @@ -175,7 +179,7 @@ let funExpr expr = let parameter = Parameter {attrs = attrs_other; lbl; defaultExpr; pat = pattern} in - collect (attrs_async @ attrsBefore) (parameter :: acc) returnExpr + collect (n + 1) (attrs_async @ attrsBefore) (parameter :: acc) returnExpr | expr -> (attrsBefore, List.rev acc, expr) in match expr with @@ -183,8 +187,8 @@ let funExpr expr = pexp_desc = Pexp_fun (Nolabel, _defaultExpr, _pattern, _returnExpr); pexp_attributes = attrs; } as expr -> - collect attrs [] {expr with pexp_attributes = []} - | expr -> collect [] [] expr + collect 0 attrs [] {expr with pexp_attributes = []} + | expr -> collect 0 [] [] expr let processBracesAttr expr = match expr.pexp_attributes with diff --git a/tests/printer/expr/asyncAwait.res b/tests/printer/expr/asyncAwait.res index 7ef4f51e..044016dd 100644 --- a/tests/printer/expr/asyncAwait.res +++ b/tests/printer/expr/asyncAwait.res @@ -82,13 +82,14 @@ let _ = await { Js.Promise.resolve(x) } -let f = async (~x, ~y) => x + y -let f = async (@foo ~x, @bar ~y) => x + y -let f = @foo async ( @bar ~x as @zz z, ~y) => x + y -let f = async x => x -let f = async x => async y => 3 -let f = async (~x) => async y => 3 -let f = async x => async (~y) => 3 -let f = async (~x) => async (~y) => 3 -let f = x => async (~y) => 3 -let f = x => async y => 3 +let f1 = async (~x, ~y) => x + y +let f2 = async (@foo ~x, @bar ~y) => x + y +let f3 = @foo async (@bar ~x as @zz z, ~y) => x + y +let f4 = async x => x +let f5 = async x => async y => 3 +let f6 = async (~x1, ~x2) => async y => 3 +let f7 = async x => async (~y) => 3 +let f8 = async (~x1, ~x2) => async (~y) => 3 +let f9 = x => async (~y) => 3 +let f10 = x => async y => 3 +let f11 = (. ~x) => (. ~y) => 3 diff --git a/tests/printer/expr/expected/asyncAwait.res.txt b/tests/printer/expr/expected/asyncAwait.res.txt index 4d648082..20b3e642 100644 --- a/tests/printer/expr/expected/asyncAwait.res.txt +++ b/tests/printer/expr/expected/asyncAwait.res.txt @@ -104,13 +104,14 @@ let _ = await { Js.Promise.resolve(x) } -let f = async (~x, ~y) => x + y -let f = async (@foo ~x, @bar ~y) => x + y -let f = async (@bar @foo ~x as @zz z, ~y) => x + y -let f = async (x) => x -let f = async (x) => async (y) => 3 -let f = async (~x) => async (y) => 3 -let f = async (x, ~y) => 3 -let f = async (~x, ~y) => 3 -let f = async (x, ~y) => 3 -let f = x => async (y) => 3 +let f1 = async (~x, ~y) => x + y +let f2 = async (@foo ~x, @bar ~y) => x + y +let f3 = async (@bar @foo ~x as @zz z, ~y) => x + y +let f4 = async (x) => x +let f5 = async (x) => async (y) => 3 +let f6 = async (~x1, ~x2) => async (y) => 3 +let f7 = async (x) => async (~y) => 3 +let f8 = async (~x1, ~x2) => async (~y) => 3 +let f9 = x => async (~y) => 3 +let f10 = x => async (y) => 3 +let f11 = (. ~x) => (. ~y) => 3 diff --git a/tests/printer/expr/expected/fun.res.txt b/tests/printer/expr/expected/fun.res.txt index 8c2d973d..a1ff38fa 100644 --- a/tests/printer/expr/expected/fun.res.txt +++ b/tests/printer/expr/expected/fun.res.txt @@ -73,7 +73,7 @@ let f = @attr (@attrOnA a, @attrOnB b) => @attr2 (@attrOnC c, @attrOnD d) => () let f = @attr (. a, b) => @attr2 (. c, d) => () let f = (@attr ~a, @attr ~b) => () -let f = (. @attr ~a, . @attr ~b) => () +let f = (. @attr ~a) => (. @attr ~b) => () let f = ( thisIsAVeryLongNaaaaaaaaaaaaaaaaaaameeeeeeeeeeeee, From 8754d94f584d73b12291a021de88e81158240a2d Mon Sep 17 00:00:00 2001 From: Cristiano Calcagno Date: Fri, 14 Oct 2022 15:51:12 +0100 Subject: [PATCH 4/6] No unnecessary parens with async. --- src/res_printer.ml | 2 +- tests/printer/expr/expected/asyncAwait.res.txt | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/res_printer.ml b/src/res_printer.ml index 60066d09..df2d66c2 100644 --- a/src/res_printer.ml +++ b/src/res_printer.ml @@ -4698,7 +4698,7 @@ and printExprFunParameters ~customLayout ~inCallback ~async ~uncurried let txtDoc = let var = printIdentLike stringLoc.txt in let var = if hasConstraint then addParens var else var in - if async then addAsync (Doc.concat [Doc.lparen; var; Doc.rparen]) else var + if async then addAsync var else var in printComments txtDoc cmtTbl stringLoc.loc (* let f = () => () *) diff --git a/tests/printer/expr/expected/asyncAwait.res.txt b/tests/printer/expr/expected/asyncAwait.res.txt index 20b3e642..5e19a99d 100644 --- a/tests/printer/expr/expected/asyncAwait.res.txt +++ b/tests/printer/expr/expected/asyncAwait.res.txt @@ -8,7 +8,7 @@ let sequentialAwait = async () => { let f = async () => () let f = async (. ()) => () -let f = async (f) => f() +let f = async f => f() let f = async (a, b) => a + b let f = async (. a, b) => a + b @@ -107,11 +107,11 @@ let _ = await { let f1 = async (~x, ~y) => x + y let f2 = async (@foo ~x, @bar ~y) => x + y let f3 = async (@bar @foo ~x as @zz z, ~y) => x + y -let f4 = async (x) => x -let f5 = async (x) => async (y) => 3 -let f6 = async (~x1, ~x2) => async (y) => 3 -let f7 = async (x) => async (~y) => 3 +let f4 = async x => x +let f5 = async x => async y => 3 +let f6 = async (~x1, ~x2) => async y => 3 +let f7 = async x => async (~y) => 3 let f8 = async (~x1, ~x2) => async (~y) => 3 let f9 = x => async (~y) => 3 -let f10 = x => async (y) => 3 +let f10 = x => async y => 3 let f11 = (. ~x) => (. ~y) => 3 From 494c8ea60e65eb57d8074e23f5c5df9714c08dc5 Mon Sep 17 00:00:00 2001 From: Cristiano Calcagno Date: Fri, 14 Oct 2022 15:52:31 +0100 Subject: [PATCH 5/6] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a48a253c..999809eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,7 @@ - Fix issue where the JSX prop has type annotation of the first class module https://github.com/rescript-lang/syntax/pull/666 - Fix issue where a spread `...x` in non-last position would not be reported as syntax error https://github.com/rescript-lang/syntax/pull/673/ - Fix issue where the formatter would delete `async` in a function with labelled arguments. +- Fix several printing issues with `async` including an infinite loop https://github.com/rescript-lang/syntax/pull/680 #### :eyeglasses: Spec Compliance From 7499178bb3fc2b1c7be44beed77ad9306afe17f9 Mon Sep 17 00:00:00 2001 From: Cristiano Calcagno Date: Sat, 15 Oct 2022 09:09:02 +0100 Subject: [PATCH 6/6] Two more examples that need fixing later. --- tests/printer/expr/asyncAwait.res | 3 +++ tests/printer/expr/expected/asyncAwait.res.txt | 3 +++ 2 files changed, 6 insertions(+) diff --git a/tests/printer/expr/asyncAwait.res b/tests/printer/expr/asyncAwait.res index 044016dd..32c77349 100644 --- a/tests/printer/expr/asyncAwait.res +++ b/tests/printer/expr/asyncAwait.res @@ -93,3 +93,6 @@ let f8 = async (~x1, ~x2) => async (~y) => 3 let f9 = x => async (~y) => 3 let f10 = x => async y => 3 let f11 = (. ~x) => (. ~y) => 3 + +let f12 = @a (@b x) => 3 +let f13 = @a @b (~x) => 3 diff --git a/tests/printer/expr/expected/asyncAwait.res.txt b/tests/printer/expr/expected/asyncAwait.res.txt index 5e19a99d..01dab207 100644 --- a/tests/printer/expr/expected/asyncAwait.res.txt +++ b/tests/printer/expr/expected/asyncAwait.res.txt @@ -115,3 +115,6 @@ let f8 = async (~x1, ~x2) => async (~y) => 3 let f9 = x => async (~y) => 3 let f10 = x => async y => 3 let f11 = (. ~x) => (. ~y) => 3 + +let f12 = @a x => 3 +let f13 = (@a @b ~x) => 3