Skip to content
This repository was archived by the owner on Jun 15, 2023. It is now read-only.

Fix several printing issues with async including an infinite loop. #680

Merged
merged 6 commits into from
Oct 15, 2022
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 @@ -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

Expand Down
20 changes: 12 additions & 8 deletions src/res_parsetree_viewer.ml
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand All @@ -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)
| {
Expand All @@ -175,16 +179,16 @@ 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
| {
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
Expand Down
2 changes: 1 addition & 1 deletion src/res_printer.ml
Original file line number Diff line number Diff line change
Expand Up @@ -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 = () => () *)
Expand Down
17 changes: 14 additions & 3 deletions tests/printer/expr/asyncAwait.res
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,17 @@ 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 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

let f12 = @a (@b x) => 3
let f13 = @a @b (~x) => 3
19 changes: 15 additions & 4 deletions tests/printer/expr/expected/asyncAwait.res.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -104,6 +104,17 @@ 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 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

let f12 = @a x => 3
let f13 = (@a @b ~x) => 3
2 changes: 1 addition & 1 deletion tests/printer/expr/expected/fun.res.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down