From e28e31c6688f10df6f5ec72a71c047421e16afc4 Mon Sep 17 00:00:00 2001 From: Cristiano Calcagno Date: Tue, 28 Jun 2022 09:40:12 +0200 Subject: [PATCH 1/4] Callbacks without exponential explosion. Follows https://github.com/rescript-lang/syntax/pull/576 --- src/res_doc.ml | 48 ++++---- src/res_doc.mli | 2 +- src/res_printer.ml | 116 ++++++++++-------- .../reason/expected/bracedJsx.res.txt | 54 +++----- .../reason/expected/comments.res.txt | 4 +- .../reason/expected/fastPipe.res.txt | 6 +- .../reason/expected/uncurrried.res.txt | 14 +-- tests/printer/expr/expected/binary.res.txt | 34 ++--- tests/printer/expr/expected/callback.res.txt | 65 ++++------ tests/printer/expr/expected/jsx.res.txt | 12 +- tests/printer/expr/expected/let.res.txt | 6 +- .../expr/expected/nestedCallbacks.res.txt | 5 + tests/printer/expr/nestedCallbacks.res | 24 ++++ tests/printer/other/expected/nesting.res.txt | 7 +- .../other/expected/signaturePicker.res.txt | 7 +- 15 files changed, 195 insertions(+), 209 deletions(-) create mode 100644 tests/printer/expr/expected/nestedCallbacks.res.txt create mode 100644 tests/printer/expr/nestedCallbacks.res diff --git a/src/res_doc.ml b/src/res_doc.ml index f997f4e4..413f7d57 100644 --- a/src/res_doc.ml +++ b/src/res_doc.ml @@ -21,7 +21,7 @@ type t = | LineSuffix of t | LineBreak of lineStyle | Group of {mutable shouldBreak: bool; doc: t} - | CustomLayout of t list + | CustomLayout of t lazy_t list | BreakParent let nil = Nil @@ -50,7 +50,7 @@ let ifBreaks t f = IfBreaks {yes = t; no = f; broken = false} let lineSuffix d = LineSuffix d let group d = Group {shouldBreak = false; doc = d} let breakableGroup ~forceBreak d = Group {shouldBreak = forceBreak; doc = d} -let customLayout gs = CustomLayout gs +let customLayout lazyDocs = CustomLayout lazyDocs let breakParent = BreakParent let space = Text " " @@ -102,13 +102,8 @@ let propagateForcedBreaks doc = let childForcesBreak = walk child in forceBreak || childForcesBreak) false children - | CustomLayout children -> - (* When using CustomLayout, we don't want to propagate forced breaks - * from the children up. By definition it picks the first layout that fits - * otherwise it takes the last of the list. - * However we do want to propagate forced breaks in the sublayouts. They - * might need to be broken. We just don't propagate them any higher here *) - let _ = walk (Concat children) in + | CustomLayout _ -> + (* TODO: this should be done lazily *) false in let _ = walk doc in @@ -119,7 +114,8 @@ let rec willBreak doc = match doc with | LineBreak (Hard | Literal) | BreakParent | Group {shouldBreak = true} -> true - | Group {doc} | Indent doc | CustomLayout (doc :: _) -> willBreak doc + | Group {doc} | Indent doc -> willBreak doc + | CustomLayout (_lazyDoc :: _) -> false (* willBreak (Lazy.force lazyDoc) *) | Concat docs -> List.exists willBreak docs | IfBreaks {yes; no} -> willBreak yes || willBreak no | _ -> false @@ -155,10 +151,7 @@ let fits w stack = | Break, IfBreaks {yes = breakDoc} -> calculate indent mode breakDoc | Flat, IfBreaks {no = flatDoc} -> calculate indent mode flatDoc | _, Concat docs -> calculateConcat indent mode docs - | _, CustomLayout (hd :: _) -> - (* TODO: if we have nested custom layouts, what we should do here? *) - calculate indent mode hd - | _, CustomLayout [] -> () + | _, CustomLayout _ -> () and calculateConcat indent mode docs = if result.contents == None then match docs with @@ -234,17 +227,18 @@ let toString ~width doc = if shouldBreak || not (fits (width - pos) ((ind, Flat, doc) :: rest)) then process ~pos lineSuffices ((ind, Break, doc) :: rest) else process ~pos lineSuffices ((ind, Flat, doc) :: rest) - | CustomLayout docs -> - let rec findGroupThatFits groups = - match groups with - | [] -> Nil - | [lastGroup] -> lastGroup - | doc :: docs -> - if fits (width - pos) ((ind, Flat, doc) :: rest) then doc - else findGroupThatFits docs + | CustomLayout lazyDocs -> + let rec findGroupThatFits lazyDocs = + match lazyDocs with + | [] -> lazy Nil + | [lazyDoc] -> lazyDoc + | lazyDoc :: lazyDocs -> + if fits (width - pos) ((ind, Flat, Lazy.force lazyDoc) :: rest) then + lazyDoc + else findGroupThatFits lazyDocs in - let doc = findGroupThatFits docs in - process ~pos lineSuffices ((ind, Flat, doc) :: rest)) + let lazyDoc = findGroupThatFits lazyDocs in + process ~pos lineSuffices ((ind, Flat, Lazy.force lazyDoc) :: rest)) | [] -> ( match lineSuffices with | [] -> () @@ -282,7 +276,7 @@ let debug t = line; text ")"; ]) - | CustomLayout docs -> + | CustomLayout lazyDocs -> group (concat [ @@ -291,7 +285,9 @@ let debug t = (concat [ line; - join ~sep:(concat [text ","; line]) (List.map toDoc docs); + join + ~sep:(concat [text ","; line]) + (List.map (fun ld -> toDoc (Lazy.force ld)) lazyDocs); ]); line; text ")"; diff --git a/src/res_doc.mli b/src/res_doc.mli index cfb79fe3..b8203c37 100644 --- a/src/res_doc.mli +++ b/src/res_doc.mli @@ -16,7 +16,7 @@ val breakableGroup : forceBreak:bool -> t -> t (* `customLayout docs` will pick the layout that fits from `docs`. * This is a very expensive computation as every layout from the list * will be checked until one fits. *) -val customLayout : t list -> t +val customLayout : t lazy_t list -> t val breakParent : t val join : sep:t -> t list -> t diff --git a/src/res_printer.ml b/src/res_printer.ml index 02359977..c290358a 100644 --- a/src/res_printer.ml +++ b/src/res_printer.ml @@ -1905,20 +1905,27 @@ and printValueBinding ~recFlag vb cmtTbl i = if ParsetreeViewer.isSinglePipeExpr vb.pvb_expr then Doc.customLayout [ - Doc.group - (Doc.concat - [ - attrs; header; patternDoc; Doc.text " ="; Doc.space; printedExpr; - ]); - Doc.group - (Doc.concat - [ - attrs; - header; - patternDoc; - Doc.text " ="; - Doc.indent (Doc.concat [Doc.line; printedExpr]); - ]); + lazy + (Doc.group + (Doc.concat + [ + attrs; + header; + patternDoc; + Doc.text " ="; + Doc.space; + printedExpr; + ])); + lazy + (Doc.group + (Doc.concat + [ + attrs; + header; + patternDoc; + Doc.text " ="; + Doc.indent (Doc.concat [Doc.line; printedExpr]); + ])); ] else let shouldIndent = @@ -3977,15 +3984,16 @@ and printArgumentsWithCallbackInFirstPosition ~uncurried args cmtTbl = * }, longArgumet, veryLooooongArgument) *) let fitsOnOneLine = - Doc.concat - [ - (if uncurried then Doc.text "(. " else Doc.lparen); - callback; - Doc.comma; - Doc.line; - printedArgs; - Doc.rparen; - ] + lazy + (Doc.concat + [ + (if uncurried then Doc.text "(. " else Doc.lparen); + callback; + Doc.comma; + Doc.line; + printedArgs; + Doc.rparen; + ]) in (* Thing.map( @@ -3995,7 +4003,7 @@ and printArgumentsWithCallbackInFirstPosition ~uncurried args cmtTbl = * arg3, * ) *) - let breakAllArgs = printArguments ~uncurried args cmtTblCopy in + let breakAllArgs = lazy (printArguments ~uncurried args cmtTblCopy) in (* Sometimes one of the non-callback arguments will break. * There might be a single line comment in there, or a multiline string etc. @@ -4012,7 +4020,7 @@ and printArgumentsWithCallbackInFirstPosition ~uncurried args cmtTbl = * In this case, we always want the arguments broken over multiple lines, * like a normal function call. *) - if Doc.willBreak printedArgs then breakAllArgs + if Doc.willBreak printedArgs then Lazy.force breakAllArgs else Doc.customLayout [fitsOnOneLine; breakAllArgs] and printArgumentsWithCallbackInLastPosition ~uncurried args cmtTbl = @@ -4023,7 +4031,7 @@ and printArgumentsWithCallbackInLastPosition ~uncurried args cmtTbl = let cmtTblCopy2 = CommentTable.copy cmtTbl in let rec loop acc args = match args with - | [] -> (Doc.nil, Doc.nil, Doc.nil) + | [] -> (lazy Doc.nil, lazy Doc.nil, lazy Doc.nil) | [(lbl, expr)] -> let lblDoc = match lbl with @@ -4034,18 +4042,22 @@ and printArgumentsWithCallbackInLastPosition ~uncurried args cmtTbl = Doc.concat [Doc.tilde; printIdentLike txt; Doc.equal; Doc.question] in let callbackFitsOnOneLine = - let pexpFunDoc = printPexpFun ~inCallback:FitsOnOneLine expr cmtTbl in - let doc = Doc.concat [lblDoc; pexpFunDoc] in - printComments doc cmtTbl expr.pexp_loc + lazy + (let pexpFunDoc = + printPexpFun ~inCallback:FitsOnOneLine expr cmtTbl + in + let doc = Doc.concat [lblDoc; pexpFunDoc] in + printComments doc cmtTbl expr.pexp_loc) in let callbackArgumentsFitsOnOneLine = - let pexpFunDoc = - printPexpFun ~inCallback:ArgumentsFitOnOneLine expr cmtTblCopy - in - let doc = Doc.concat [lblDoc; pexpFunDoc] in - printComments doc cmtTblCopy expr.pexp_loc + lazy + (let pexpFunDoc = + printPexpFun ~inCallback:ArgumentsFitOnOneLine expr cmtTblCopy + in + let doc = Doc.concat [lblDoc; pexpFunDoc] in + printComments doc cmtTblCopy expr.pexp_loc) in - ( Doc.concat (List.rev acc), + ( lazy (Doc.concat (List.rev acc)), callbackFitsOnOneLine, callbackArgumentsFitsOnOneLine ) | arg :: args -> @@ -4056,13 +4068,14 @@ and printArgumentsWithCallbackInLastPosition ~uncurried args cmtTbl = (* Thing.map(foo, (arg1, arg2) => MyModuleBlah.toList(argument)) *) let fitsOnOneLine = - Doc.concat - [ - (if uncurried then Doc.text "(." else Doc.lparen); - printedArgs; - callback; - Doc.rparen; - ] + lazy + (Doc.concat + [ + (if uncurried then Doc.text "(." else Doc.lparen); + Lazy.force printedArgs; + Lazy.force callback; + Doc.rparen; + ]) in (* Thing.map(longArgumet, veryLooooongArgument, (arg1, arg2) => @@ -4070,13 +4083,14 @@ and printArgumentsWithCallbackInLastPosition ~uncurried args cmtTbl = * ) *) let arugmentsFitOnOneLine = - Doc.concat - [ - (if uncurried then Doc.text "(." else Doc.lparen); - printedArgs; - Doc.breakableGroup ~forceBreak:true callback2; - Doc.rparen; - ] + lazy + (Doc.concat + [ + (if uncurried then Doc.text "(." else Doc.lparen); + Lazy.force printedArgs; + Doc.breakableGroup ~forceBreak:true (Lazy.force callback2); + Doc.rparen; + ]) in (* Thing.map( @@ -4086,7 +4100,7 @@ and printArgumentsWithCallbackInLastPosition ~uncurried args cmtTbl = * (param1, parm2) => doStuff(param1, parm2) * ) *) - let breakAllArgs = printArguments ~uncurried args cmtTblCopy2 in + let breakAllArgs = lazy (printArguments ~uncurried args cmtTblCopy2) in (* Sometimes one of the non-callback arguments will break. * There might be a single line comment in there, or a multiline string etc. @@ -4103,7 +4117,7 @@ and printArgumentsWithCallbackInLastPosition ~uncurried args cmtTbl = * In this case, we always want the arguments broken over multiple lines, * like a normal function call. *) - if Doc.willBreak printedArgs then breakAllArgs + if Doc.willBreak (Lazy.force printedArgs) then Lazy.force breakAllArgs else Doc.customLayout [fitsOnOneLine; arugmentsFitOnOneLine; breakAllArgs] and printArguments ~uncurried diff --git a/tests/conversion/reason/expected/bracedJsx.res.txt b/tests/conversion/reason/expected/bracedJsx.res.txt index b49e82fe..522b6c1b 100644 --- a/tests/conversion/reason/expected/bracedJsx.res.txt +++ b/tests/conversion/reason/expected/bracedJsx.res.txt @@ -50,55 +50,45 @@ module Styles = { let make = () => { let containerRef = React.useRef(Js.Nullable.null) - let (state, send) = React.useReducer((state, action) => - switch action { + let (state, send) = React.useReducer((state, action) => switch action { | RunCommand => { input: "", history: Array.concat( state.history, - [ - User(state.input), - switch state.input->Js.String.trim { + [User(state.input), switch state.input->Js.String.trim { | "" => System("") - | "help" => - System(`available commands: + | "help" => System(`available commands: - help - ls - cat `) - | "ls" => - System(`- hack-website.sh + | "ls" => System(`- hack-website.sh - go-to-home.sh - nuclear-codes.txt`) | "cat" => System("cat: missing argument") | "cat hack-website.sh" - | "cat ./hack-website.sh" => - System("# seriously?\necho \"lol\"") + | "cat ./hack-website.sh" => System("# seriously?\necho \"lol\"") | "hack-website.sh" - | "./hack-website.sh" => - System("lol") + | "./hack-website.sh" => System("lol") | "cat nuclear-codes.txt" - | "cat ./nuclear-codes.txt" => - System("000000") + | "cat ./nuclear-codes.txt" => System("000000") | "go-to-home.sh" - | "./go-to-home.sh" => - Js.Global.setTimeout(() => ReasonReact.Router.push("/"), 1_000)->ignore + | "./go-to-home.sh" => Js.Global.setTimeout( + () => ReasonReact.Router.push("/"), + 1_000, + )->ignore System("Redirecting ...") | "cat go-to-home.sh" - | "cat ./go-to-home.sh" => - System("ReasonReact.Router.push(\"/\")") + | "cat ./go-to-home.sh" => System("ReasonReact.Router.push(\"/\")") | _ => System("command not found: " ++ (state.input ++ "\ntry command 'help'")) - }, - ], + }], ), } | SetValue(input) => {...state, input} - } - , {history: [], input: ""}) + }, {history: [], input: ""}) React.useEffect1(() => { switch containerRef.current->Js.Nullable.toOption { - | Some(containerRef) => - open Webapi.Dom + | Some(containerRef) => open Webapi.Dom containerRef->Element.setScrollTop(containerRef->Element.scrollHeight->float_of_int) | None => () } @@ -112,18 +102,12 @@ let make = () => { className=Styles.terminal onClick={event => (event->ReactEvent.Mouse.target)["querySelector"]("input")["focus"]()} ref={containerRef->ReactDOMRe.Ref.domRef}> - {state.history - ->Array.mapWithIndex((index, item) => -
- {ReasonReact.string( - switch item { + {state.history->Array.mapWithIndex((index, item) => +
{ReasonReact.string(switch item { | User(value) => userPrefix ++ value | System(value) => value - }, - )} -
- ) - ->ReasonReact.array} + })}
+ )->ReasonReact.array}
{userPrefix->ReasonReact.string} { { // First comment - let x = 0 +let x = 0 x + x // Closing comment }) ignore((_xxx, _yyy) => { // First comment - let x = 0 +let x = 0 x + x // Closing comment }) diff --git a/tests/conversion/reason/expected/fastPipe.res.txt b/tests/conversion/reason/expected/fastPipe.res.txt index a7007b68..2fb1b363 100644 --- a/tests/conversion/reason/expected/fastPipe.res.txt +++ b/tests/conversion/reason/expected/fastPipe.res.txt @@ -15,9 +15,9 @@ let x = @attr ((@attr2 a)->f(b)->c(d)) Route.urlToRoute(url)->ChangeView->self.send let aggregateTotal = (forecast, ~audienceType) => - Js.Nullable.toOption(forecast["audiences"]) - ->Option.flatMap(item => Js.Dict.get(item, audienceType)) - ->Option.map(item => { + Js.Nullable.toOption(forecast["audiences"])->Option.flatMap(item => + Js.Dict.get(item, audienceType) + )->Option.map(item => { pages: item["reach"]["pages"], views: item["reach"]["views"], sample: item["reach"]["sample"], diff --git a/tests/conversion/reason/expected/uncurrried.res.txt b/tests/conversion/reason/expected/uncurrried.res.txt index b273f54a..c5ed26db 100644 --- a/tests/conversion/reason/expected/uncurrried.res.txt +++ b/tests/conversion/reason/expected/uncurrried.res.txt @@ -51,14 +51,8 @@ let () = { let _ = library.getBalance(. account)->Promise.Js.catch(_ => Promise.resolved(None)) -let _ = - library.getBalance(. account) - ->Promise.Js.catch(_ => Promise.resolved(None)) - ->Promise.get(newBalance => - dispatch( - LoadAddress( - account, - newBalance->Belt.Option.flatMap(balance => Eth.make(balance.toString(.))), - ), - ) +let _ = library.getBalance(. account)->Promise.Js.catch(_ => Promise.resolved(None))->Promise.get( + newBalance => dispatch(LoadAddress(account, newBalance->Belt.Option.flatMap(balance => + Eth.make(balance.toString(.)) + ))), ) diff --git a/tests/printer/expr/expected/binary.res.txt b/tests/printer/expr/expected/binary.res.txt index ff8491a2..a107dc1f 100644 --- a/tests/printer/expr/expected/binary.res.txt +++ b/tests/printer/expr/expected/binary.res.txt @@ -472,22 +472,18 @@ foo := | _ => 1 } -
- {possibleGradeValues - |> List.filter(g => g < state.maxGrade) - |> List.map(possibleGradeValue => +
{possibleGradeValues |> List.filter(g => + g < state.maxGrade + ) |> List.map(possibleGradeValue => - ) - |> Array.of_list - |> ReasonReact.array} -
+ ) |> Array.of_list |> ReasonReact.array}
let aggregateTotal = (forecast, ~audienceType) => - Js.Nullable.toOption(forecast["audiences"]) - ->Option.flatMap(item => Js.Dict.get(item, audienceType)) - ->Option.map(item => { + Js.Nullable.toOption(forecast["audiences"])->Option.flatMap(item => + Js.Dict.get(item, audienceType) + )->Option.map(item => { pages: item["reach"]["pages"], views: item["reach"]["views"], sample: item["reach"]["sample"], @@ -495,16 +491,12 @@ let aggregateTotal = (forecast, ~audienceType) => React.useEffect4(() => { switch (context.library, context.account) { - | (Some(library), Some(account)) => - library.getBalance(. account) - ->Promise.Js.catch(_ => {Promise.resolved(None)}) - ->Promise.get(newBalance => { - dispatch( - LoadAddress( - account, - newBalance->Belt.Option.flatMap(balance => Eth.make(balance.toString(.))), - ), - ) + | (Some(library), Some(account)) => library.getBalance(. account)->Promise.Js.catch(_ => { + Promise.resolved(None) + })->Promise.get(newBalance => { + dispatch(LoadAddress(account, newBalance->Belt.Option.flatMap(balance => + Eth.make(balance.toString(.)) + ))) }) None diff --git a/tests/printer/expr/expected/callback.res.txt b/tests/printer/expr/expected/callback.res.txt index 50393c39..1e439ebe 100644 --- a/tests/printer/expr/expected/callback.res.txt +++ b/tests/printer/expr/expected/callback.res.txt @@ -60,10 +60,10 @@ let _ = { } } -let trees = - possibilities->Belt.Array.mapU((. combination) => - combination->Belt.Array.reduceU(Nil, (. tree, curr) => tree->insert(curr)) - ) +let trees = possibilities->Belt.Array.mapU((. combination) => combination->Belt.Array.reduceU( + Nil, + (. tree, curr) => tree->insert(curr), + )) let set = mapThatHasAVeryLongName->Belt.Map.String.getExn(website)->Belt.Set.Int.add(user) @@ -82,11 +82,10 @@ let add2 = (y: coll, e: key) => } let add2 = (y: coll, e: key) => - if ( - possibilities->Belt.Array.mapU((. combination) => - combination->Belt.Array.reduceU(Nil, (. tree, curr) => tree->insert(curr)) - ) - ) { + if possibilities->Belt.Array.mapU((. combination) => combination->Belt.Array.reduceU(Nil, (. + tree, + curr, + ) => tree->insert(curr))) { y } else { list{e, ...y} @@ -153,25 +152,22 @@ Thing.map( aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaarg4, ) -List.iter(x => - switch x { +List.iter(x => switch x { | ({txt: Lident(name)}, x) => field(name, x) | _ => () - } -, fields) + }, fields) foo(key => { switch bla { // cancellation =D - | None => true +| None => true } }) foo(_ => { switch bar { | None => () - | Some(_) => - a := b + | Some(_) => a := b Js.log("hi") } }) @@ -180,17 +176,13 @@ foo(list => list()) foo(\"switch" => \"switch"()) // the [] of the array should break -[ - fn(x => { +[fn(x => { let _ = x - }), - fn(y => { + }), fn(y => { let _ = y - }), - fn(z => { + }), fn(z => { let _ = z - }), -] + })] // similar, the jsx tree should be broken over multiple lines let f = () => { @@ -201,13 +193,9 @@ let f = () => { | Done(Error(_)) => "Error"->React.string | Done(Ok(users)) => <> - {reloadableUser.last->AsyncData.isLoading ? "Loading next page"->React.string : React.null} @@ -226,13 +214,11 @@ myPromise->Js.Promise.then_(value => { Js.Promise.resolve(-2) }, _) -let decoratorTags = - items - ->Js.Array2.filter(items => {items.category === Decorators}) - ->Belt.Array.map(item => { - - - +let decoratorTags = items->Js.Array2.filter(items => { + items.category === Decorators + })->Belt.Array.map(item => { + + }) // Comments should still be printed here (callback in last position) @@ -301,8 +287,9 @@ let make = fn(( }) // comments should not disappear on the pattern -let /* a */ decoratorTags /* b */ = - items->Js.Array2.filter(items => {items.category === Decorators}) +let /* a */ decoratorTags /* b */ = items->Js.Array2.filter(items => { + items.category === Decorators +}) let /* a */ decoratorTags /* b */ = items->Js.Array2.filter(items => { items.category === Decorators || diff --git a/tests/printer/expr/expected/jsx.res.txt b/tests/printer/expr/expected/jsx.res.txt index e6b0c00d..927c5e2f 100644 --- a/tests/printer/expr/expected/jsx.res.txt +++ b/tests/printer/expr/expected/jsx.res.txt @@ -277,17 +277,13 @@ let x = let x = test
} nav={} /> -
- {possibleGradeValues - |> List.filter(g => g <= state.maxGrade) - |> List.map(possibleGradeValue => +
{possibleGradeValues |> List.filter(g => + g <= state.maxGrade + ) |> List.map(possibleGradeValue => - ) - |> Array.of_list - |> ReasonReact.array} -
+ ) |> Array.of_list |> ReasonReact.array}
// https://github.com/rescript-lang/syntax/issues/113
{Js.log(a <= 10)}
diff --git a/tests/printer/expr/expected/let.res.txt b/tests/printer/expr/expected/let.res.txt index 879efc28..fd1f0bb6 100644 --- a/tests/printer/expr/expected/let.res.txt +++ b/tests/printer/expr/expected/let.res.txt @@ -47,11 +47,7 @@ let f = x => { ->Option.flatMap(Js.Json.decodeString) ->Option.map(Js.Date.fromString) - let b = - x - ->Js.Dict.get("wm-property") - ->Option.flatMap(Js.Json.decodeString) - ->Option.flatMap(x => + let b = x->Js.Dict.get("wm-property")->Option.flatMap(Js.Json.decodeString)->Option.flatMap(x => switch x { | "like-of" => Some(#like) | "repost-of" => Some(#repost) diff --git a/tests/printer/expr/expected/nestedCallbacks.res.txt b/tests/printer/expr/expected/nestedCallbacks.res.txt new file mode 100644 index 00000000..e3c35fbd --- /dev/null +++ b/tests/printer/expr/expected/nestedCallbacks.res.txt @@ -0,0 +1,5 @@ +let foo = () => bar(x => bar(x => bar(x => bar(x => bar(x => bar(x => bar(x => bar(x => bar(x => + bar(x => bar(x => bar(x => bar(x => bar(x => bar(x => bar(x => bar(x => + bar(x => bar(x => bar(x => bar(x => bar(x => x))))) + )))))))) + ))))))))) diff --git a/tests/printer/expr/nestedCallbacks.res b/tests/printer/expr/nestedCallbacks.res new file mode 100644 index 00000000..cc2f9c89 --- /dev/null +++ b/tests/printer/expr/nestedCallbacks.res @@ -0,0 +1,24 @@ +let foo = () => + bar(x => + bar(x => + bar(x => + bar(x => + bar(x => + bar(x => + bar(x => + bar(x => + bar(x => + bar(x => + bar(x => + bar(x => + bar(x => + bar(x => + bar(x => + bar(x => + bar(x => + bar(x => + bar(x => + bar(x => + bar(x => + bar(x => x) + ))))))))))))))))))))) \ No newline at end of file diff --git a/tests/printer/other/expected/nesting.res.txt b/tests/printer/other/expected/nesting.res.txt index 0cafca83..20868e36 100644 --- a/tests/printer/other/expected/nesting.res.txt +++ b/tests/printer/other/expected/nesting.res.txt @@ -3,7 +3,7 @@ let unitsCommands = state.units->Js.Array2.mapi(( i, ) => { // n^2 - let res = [] +let res = [] state.units->Js.Array2.forEachi(( {unit: unitThatMightBeAttacking, coordinates: unitThatMightBeAttackingCoordinates}, j, @@ -13,8 +13,9 @@ let unitsCommands = state.units->Js.Array2.mapi(( unitThatMightBeAttacking.timeline, unitThatMightBeAttacking.currentFrame, ).effect { - | Some(UnitAttack({damage, hitBox: _})) => - let unitThatMightBeAttackingHitBox_ = Unit.hitBox(unitThatMightBeAttacking) + | Some(UnitAttack({damage, hitBox: _})) => let unitThatMightBeAttackingHitBox_ = Unit.hitBox( + unitThatMightBeAttacking, + ) let unitThatMightBeAttackingHitBox = { ...unitThatMightBeAttackingHitBox_, x: unitThatMightBeAttackingCoordinates.x +. unitThatMightBeAttackingHitBox_.x, diff --git a/tests/printer/other/expected/signaturePicker.res.txt b/tests/printer/other/expected/signaturePicker.res.txt index f73d98b8..1ee6d98b 100644 --- a/tests/printer/other/expected/signaturePicker.res.txt +++ b/tests/printer/other/expected/signaturePicker.res.txt @@ -29,14 +29,11 @@ let make = () => { Date: Tue, 28 Jun 2022 10:04:27 +0200 Subject: [PATCH 2/4] On Custom:Layout, propagate force breaks later. --- src/res_doc.ml | 18 +++---- .../reason/expected/bracedJsx.res.txt | 48 ++++++++++++------- .../reason/expected/comments.res.txt | 4 +- tests/printer/expr/expected/binary.res.txt | 15 +++--- tests/printer/expr/expected/callback.res.txt | 16 ++++--- tests/printer/other/expected/nesting.res.txt | 7 ++- 6 files changed, 64 insertions(+), 44 deletions(-) diff --git a/src/res_doc.ml b/src/res_doc.ml index 413f7d57..25459ea6 100644 --- a/src/res_doc.ml +++ b/src/res_doc.ml @@ -21,7 +21,7 @@ type t = | LineSuffix of t | LineBreak of lineStyle | Group of {mutable shouldBreak: bool; doc: t} - | CustomLayout of t lazy_t list + | CustomLayout of {groups: t lazy_t list; mutable forceBreak: bool} | BreakParent let nil = Nil @@ -50,7 +50,7 @@ let ifBreaks t f = IfBreaks {yes = t; no = f; broken = false} let lineSuffix d = LineSuffix d let group d = Group {shouldBreak = false; doc = d} let breakableGroup ~forceBreak d = Group {shouldBreak = forceBreak; doc = d} -let customLayout lazyDocs = CustomLayout lazyDocs +let customLayout lazyDocs = CustomLayout {groups = lazyDocs; forceBreak = false} let breakParent = BreakParent let space = Text " " @@ -102,8 +102,8 @@ let propagateForcedBreaks doc = let childForcesBreak = walk child in forceBreak || childForcesBreak) false children - | CustomLayout _ -> - (* TODO: this should be done lazily *) + | CustomLayout cl -> + cl.forceBreak <- true; false in let _ = walk doc in @@ -115,7 +115,7 @@ let rec willBreak doc = | LineBreak (Hard | Literal) | BreakParent | Group {shouldBreak = true} -> true | Group {doc} | Indent doc -> willBreak doc - | CustomLayout (_lazyDoc :: _) -> false (* willBreak (Lazy.force lazyDoc) *) + | CustomLayout {groups = _lazyDoc :: _} -> false | Concat docs -> List.exists willBreak docs | IfBreaks {yes; no} -> willBreak yes || willBreak no | _ -> false @@ -227,7 +227,7 @@ let toString ~width doc = if shouldBreak || not (fits (width - pos) ((ind, Flat, doc) :: rest)) then process ~pos lineSuffices ((ind, Break, doc) :: rest) else process ~pos lineSuffices ((ind, Flat, doc) :: rest) - | CustomLayout lazyDocs -> + | CustomLayout {groups = lazyDocs; forceBreak} -> let rec findGroupThatFits lazyDocs = match lazyDocs with | [] -> lazy Nil @@ -238,7 +238,9 @@ let toString ~width doc = else findGroupThatFits lazyDocs in let lazyDoc = findGroupThatFits lazyDocs in - process ~pos lineSuffices ((ind, Flat, Lazy.force lazyDoc) :: rest)) + let doc = Lazy.force lazyDoc in + if forceBreak then propagateForcedBreaks doc; + process ~pos lineSuffices ((ind, Flat, doc) :: rest)) | [] -> ( match lineSuffices with | [] -> () @@ -276,7 +278,7 @@ let debug t = line; text ")"; ]) - | CustomLayout lazyDocs -> + | CustomLayout {groups = lazyDocs} -> group (concat [ diff --git a/tests/conversion/reason/expected/bracedJsx.res.txt b/tests/conversion/reason/expected/bracedJsx.res.txt index 522b6c1b..355ce1a5 100644 --- a/tests/conversion/reason/expected/bracedJsx.res.txt +++ b/tests/conversion/reason/expected/bracedJsx.res.txt @@ -50,45 +50,55 @@ module Styles = { let make = () => { let containerRef = React.useRef(Js.Nullable.null) - let (state, send) = React.useReducer((state, action) => switch action { + let (state, send) = React.useReducer((state, action) => + switch action { | RunCommand => { input: "", history: Array.concat( state.history, - [User(state.input), switch state.input->Js.String.trim { + [ + User(state.input), + switch state.input->Js.String.trim { | "" => System("") - | "help" => System(`available commands: + | "help" => + System(`available commands: - help - ls - cat `) - | "ls" => System(`- hack-website.sh + | "ls" => + System(`- hack-website.sh - go-to-home.sh - nuclear-codes.txt`) | "cat" => System("cat: missing argument") | "cat hack-website.sh" - | "cat ./hack-website.sh" => System("# seriously?\necho \"lol\"") + | "cat ./hack-website.sh" => + System("# seriously?\necho \"lol\"") | "hack-website.sh" - | "./hack-website.sh" => System("lol") + | "./hack-website.sh" => + System("lol") | "cat nuclear-codes.txt" - | "cat ./nuclear-codes.txt" => System("000000") + | "cat ./nuclear-codes.txt" => + System("000000") | "go-to-home.sh" - | "./go-to-home.sh" => Js.Global.setTimeout( - () => ReasonReact.Router.push("/"), - 1_000, - )->ignore + | "./go-to-home.sh" => + Js.Global.setTimeout(() => ReasonReact.Router.push("/"), 1_000)->ignore System("Redirecting ...") | "cat go-to-home.sh" - | "cat ./go-to-home.sh" => System("ReasonReact.Router.push(\"/\")") + | "cat ./go-to-home.sh" => + System("ReasonReact.Router.push(\"/\")") | _ => System("command not found: " ++ (state.input ++ "\ntry command 'help'")) - }], + }, + ], ), } | SetValue(input) => {...state, input} - }, {history: [], input: ""}) + } + , {history: [], input: ""}) React.useEffect1(() => { switch containerRef.current->Js.Nullable.toOption { - | Some(containerRef) => open Webapi.Dom + | Some(containerRef) => + open Webapi.Dom containerRef->Element.setScrollTop(containerRef->Element.scrollHeight->float_of_int) | None => () } @@ -103,10 +113,14 @@ let make = () => { onClick={event => (event->ReactEvent.Mouse.target)["querySelector"]("input")["focus"]()} ref={containerRef->ReactDOMRe.Ref.domRef}> {state.history->Array.mapWithIndex((index, item) => -
{ReasonReact.string(switch item { +
+ {ReasonReact.string( + switch item { | User(value) => userPrefix ++ value | System(value) => value - })}
+ }, + )} +
)->ReasonReact.array}
{userPrefix->ReasonReact.string} diff --git a/tests/conversion/reason/expected/comments.res.txt b/tests/conversion/reason/expected/comments.res.txt index c11a1955..948e3ba4 100644 --- a/tests/conversion/reason/expected/comments.res.txt +++ b/tests/conversion/reason/expected/comments.res.txt @@ -646,14 +646,14 @@ while trueThing { ignore((_really, _long, _printWidth, _exceeded, _here) => { // First comment -let x = 0 + let x = 0 x + x // Closing comment }) ignore((_xxx, _yyy) => { // First comment -let x = 0 + let x = 0 x + x // Closing comment }) diff --git a/tests/printer/expr/expected/binary.res.txt b/tests/printer/expr/expected/binary.res.txt index a107dc1f..2ab41084 100644 --- a/tests/printer/expr/expected/binary.res.txt +++ b/tests/printer/expr/expected/binary.res.txt @@ -491,13 +491,14 @@ let aggregateTotal = (forecast, ~audienceType) => React.useEffect4(() => { switch (context.library, context.account) { - | (Some(library), Some(account)) => library.getBalance(. account)->Promise.Js.catch(_ => { - Promise.resolved(None) - })->Promise.get(newBalance => { - dispatch(LoadAddress(account, newBalance->Belt.Option.flatMap(balance => - Eth.make(balance.toString(.)) - ))) - }) + | (Some(library), Some(account)) => + library.getBalance(. account)->Promise.Js.catch(_ => {Promise.resolved(None)})->Promise.get( + newBalance => { + dispatch(LoadAddress(account, newBalance->Belt.Option.flatMap(balance => + Eth.make(balance.toString(.)) + ))) + }, + ) None | _ => None diff --git a/tests/printer/expr/expected/callback.res.txt b/tests/printer/expr/expected/callback.res.txt index 1e439ebe..e79ab130 100644 --- a/tests/printer/expr/expected/callback.res.txt +++ b/tests/printer/expr/expected/callback.res.txt @@ -152,22 +152,25 @@ Thing.map( aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaarg4, ) -List.iter(x => switch x { +List.iter(x => + switch x { | ({txt: Lident(name)}, x) => field(name, x) | _ => () - }, fields) + } +, fields) foo(key => { switch bla { // cancellation =D -| None => true + | None => true } }) foo(_ => { switch bar { | None => () - | Some(_) => a := b + | Some(_) => + a := b Js.log("hi") } }) @@ -217,8 +220,9 @@ myPromise->Js.Promise.then_(value => { let decoratorTags = items->Js.Array2.filter(items => { items.category === Decorators })->Belt.Array.map(item => { - - + + + }) // Comments should still be printed here (callback in last position) diff --git a/tests/printer/other/expected/nesting.res.txt b/tests/printer/other/expected/nesting.res.txt index 20868e36..0cafca83 100644 --- a/tests/printer/other/expected/nesting.res.txt +++ b/tests/printer/other/expected/nesting.res.txt @@ -3,7 +3,7 @@ let unitsCommands = state.units->Js.Array2.mapi(( i, ) => { // n^2 -let res = [] + let res = [] state.units->Js.Array2.forEachi(( {unit: unitThatMightBeAttacking, coordinates: unitThatMightBeAttackingCoordinates}, j, @@ -13,9 +13,8 @@ let res = [] unitThatMightBeAttacking.timeline, unitThatMightBeAttacking.currentFrame, ).effect { - | Some(UnitAttack({damage, hitBox: _})) => let unitThatMightBeAttackingHitBox_ = Unit.hitBox( - unitThatMightBeAttacking, - ) + | Some(UnitAttack({damage, hitBox: _})) => + let unitThatMightBeAttackingHitBox_ = Unit.hitBox(unitThatMightBeAttacking) let unitThatMightBeAttackingHitBox = { ...unitThatMightBeAttackingHitBox_, x: unitThatMightBeAttackingCoordinates.x +. unitThatMightBeAttackingHitBox_.x, From 5576952929121e733d02afeb37ed43522f0502f3 Mon Sep 17 00:00:00 2001 From: Cristiano Calcagno Date: Tue, 28 Jun 2022 10:16:11 +0200 Subject: [PATCH 3/4] Restore wilBreak functionality. --- src/res_doc.ml | 2 +- .../reason/expected/bracedJsx.res.txt | 6 +++-- .../reason/expected/fastPipe.res.txt | 6 ++--- tests/printer/expr/expected/binary.res.txt | 20 +++++++------- tests/printer/expr/expected/callback.res.txt | 27 ++++++++++++------- tests/printer/expr/expected/let.res.txt | 6 ++++- 6 files changed, 41 insertions(+), 26 deletions(-) diff --git a/src/res_doc.ml b/src/res_doc.ml index 25459ea6..95d50a4e 100644 --- a/src/res_doc.ml +++ b/src/res_doc.ml @@ -115,7 +115,7 @@ let rec willBreak doc = | LineBreak (Hard | Literal) | BreakParent | Group {shouldBreak = true} -> true | Group {doc} | Indent doc -> willBreak doc - | CustomLayout {groups = _lazyDoc :: _} -> false + | CustomLayout {groups = lazyDoc :: _} -> willBreak (Lazy.force lazyDoc) | Concat docs -> List.exists willBreak docs | IfBreaks {yes; no} -> willBreak yes || willBreak no | _ -> false diff --git a/tests/conversion/reason/expected/bracedJsx.res.txt b/tests/conversion/reason/expected/bracedJsx.res.txt index 355ce1a5..b49e82fe 100644 --- a/tests/conversion/reason/expected/bracedJsx.res.txt +++ b/tests/conversion/reason/expected/bracedJsx.res.txt @@ -112,7 +112,8 @@ let make = () => { className=Styles.terminal onClick={event => (event->ReactEvent.Mouse.target)["querySelector"]("input")["focus"]()} ref={containerRef->ReactDOMRe.Ref.domRef}> - {state.history->Array.mapWithIndex((index, item) => + {state.history + ->Array.mapWithIndex((index, item) =>
{ReasonReact.string( switch item { @@ -121,7 +122,8 @@ let make = () => { }, )}
- )->ReasonReact.array} + ) + ->ReasonReact.array}
{userPrefix->ReasonReact.string} {f(b)->c(d)) Route.urlToRoute(url)->ChangeView->self.send let aggregateTotal = (forecast, ~audienceType) => - Js.Nullable.toOption(forecast["audiences"])->Option.flatMap(item => - Js.Dict.get(item, audienceType) - )->Option.map(item => { + Js.Nullable.toOption(forecast["audiences"]) + ->Option.flatMap(item => Js.Dict.get(item, audienceType)) + ->Option.map(item => { pages: item["reach"]["pages"], views: item["reach"]["views"], sample: item["reach"]["sample"], diff --git a/tests/printer/expr/expected/binary.res.txt b/tests/printer/expr/expected/binary.res.txt index 2ab41084..7b8bf4c9 100644 --- a/tests/printer/expr/expected/binary.res.txt +++ b/tests/printer/expr/expected/binary.res.txt @@ -481,9 +481,9 @@ foo := ) |> Array.of_list |> ReasonReact.array}
let aggregateTotal = (forecast, ~audienceType) => - Js.Nullable.toOption(forecast["audiences"])->Option.flatMap(item => - Js.Dict.get(item, audienceType) - )->Option.map(item => { + Js.Nullable.toOption(forecast["audiences"]) + ->Option.flatMap(item => Js.Dict.get(item, audienceType)) + ->Option.map(item => { pages: item["reach"]["pages"], views: item["reach"]["views"], sample: item["reach"]["sample"], @@ -492,13 +492,13 @@ let aggregateTotal = (forecast, ~audienceType) => React.useEffect4(() => { switch (context.library, context.account) { | (Some(library), Some(account)) => - library.getBalance(. account)->Promise.Js.catch(_ => {Promise.resolved(None)})->Promise.get( - newBalance => { - dispatch(LoadAddress(account, newBalance->Belt.Option.flatMap(balance => - Eth.make(balance.toString(.)) - ))) - }, - ) + library.getBalance(. account) + ->Promise.Js.catch(_ => {Promise.resolved(None)}) + ->Promise.get(newBalance => { + dispatch(LoadAddress(account, newBalance->Belt.Option.flatMap(balance => + Eth.make(balance.toString(.)) + ))) + }) None | _ => None diff --git a/tests/printer/expr/expected/callback.res.txt b/tests/printer/expr/expected/callback.res.txt index e79ab130..5282b929 100644 --- a/tests/printer/expr/expected/callback.res.txt +++ b/tests/printer/expr/expected/callback.res.txt @@ -179,13 +179,17 @@ foo(list => list()) foo(\"switch" => \"switch"()) // the [] of the array should break -[fn(x => { +[ + fn(x => { let _ = x - }), fn(y => { + }), + fn(y => { let _ = y - }), fn(z => { + }), + fn(z => { let _ = z - })] + }), +] // similar, the jsx tree should be broken over multiple lines let f = () => { @@ -196,9 +200,13 @@ let f = () => { | Done(Error(_)) => "Error"->React.string | Done(Ok(users)) => <> -
    {users->Array.map(user => { +
      + {users + ->Array.map(user => {
    • {user.username->React.string}
    • - })->React.array}
    + }) + ->React.array} +
{reloadableUser.last->AsyncData.isLoading ? "Loading next page"->React.string : React.null} @@ -217,9 +225,10 @@ myPromise->Js.Promise.then_(value => { Js.Promise.resolve(-2) }, _) -let decoratorTags = items->Js.Array2.filter(items => { - items.category === Decorators - })->Belt.Array.map(item => { +let decoratorTags = + items + ->Js.Array2.filter(items => {items.category === Decorators}) + ->Belt.Array.map(item => { diff --git a/tests/printer/expr/expected/let.res.txt b/tests/printer/expr/expected/let.res.txt index fd1f0bb6..879efc28 100644 --- a/tests/printer/expr/expected/let.res.txt +++ b/tests/printer/expr/expected/let.res.txt @@ -47,7 +47,11 @@ let f = x => { ->Option.flatMap(Js.Json.decodeString) ->Option.map(Js.Date.fromString) - let b = x->Js.Dict.get("wm-property")->Option.flatMap(Js.Json.decodeString)->Option.flatMap(x => + let b = + x + ->Js.Dict.get("wm-property") + ->Option.flatMap(Js.Json.decodeString) + ->Option.flatMap(x => switch x { | "like-of" => Some(#like) | "repost-of" => Some(#repost) From 14429566e9f836e6eef6596b8f182278c890f8c7 Mon Sep 17 00:00:00 2001 From: Cristiano Calcagno Date: Tue, 28 Jun 2022 10:22:25 +0200 Subject: [PATCH 4/4] Revert "Restore wilBreak functionality." as it breaks roundtrip tests. This reverts commit 5576952929121e733d02afeb37ed43522f0502f3. --- src/res_doc.ml | 2 +- .../reason/expected/bracedJsx.res.txt | 6 ++--- .../reason/expected/fastPipe.res.txt | 6 ++--- tests/printer/expr/expected/binary.res.txt | 20 +++++++------- tests/printer/expr/expected/callback.res.txt | 27 +++++++------------ tests/printer/expr/expected/let.res.txt | 6 +---- 6 files changed, 26 insertions(+), 41 deletions(-) diff --git a/src/res_doc.ml b/src/res_doc.ml index 95d50a4e..25459ea6 100644 --- a/src/res_doc.ml +++ b/src/res_doc.ml @@ -115,7 +115,7 @@ let rec willBreak doc = | LineBreak (Hard | Literal) | BreakParent | Group {shouldBreak = true} -> true | Group {doc} | Indent doc -> willBreak doc - | CustomLayout {groups = lazyDoc :: _} -> willBreak (Lazy.force lazyDoc) + | CustomLayout {groups = _lazyDoc :: _} -> false | Concat docs -> List.exists willBreak docs | IfBreaks {yes; no} -> willBreak yes || willBreak no | _ -> false diff --git a/tests/conversion/reason/expected/bracedJsx.res.txt b/tests/conversion/reason/expected/bracedJsx.res.txt index b49e82fe..355ce1a5 100644 --- a/tests/conversion/reason/expected/bracedJsx.res.txt +++ b/tests/conversion/reason/expected/bracedJsx.res.txt @@ -112,8 +112,7 @@ let make = () => { className=Styles.terminal onClick={event => (event->ReactEvent.Mouse.target)["querySelector"]("input")["focus"]()} ref={containerRef->ReactDOMRe.Ref.domRef}> - {state.history - ->Array.mapWithIndex((index, item) => + {state.history->Array.mapWithIndex((index, item) =>
{ReasonReact.string( switch item { @@ -122,8 +121,7 @@ let make = () => { }, )}
- ) - ->ReasonReact.array} + )->ReasonReact.array}
{userPrefix->ReasonReact.string} {f(b)->c(d)) Route.urlToRoute(url)->ChangeView->self.send let aggregateTotal = (forecast, ~audienceType) => - Js.Nullable.toOption(forecast["audiences"]) - ->Option.flatMap(item => Js.Dict.get(item, audienceType)) - ->Option.map(item => { + Js.Nullable.toOption(forecast["audiences"])->Option.flatMap(item => + Js.Dict.get(item, audienceType) + )->Option.map(item => { pages: item["reach"]["pages"], views: item["reach"]["views"], sample: item["reach"]["sample"], diff --git a/tests/printer/expr/expected/binary.res.txt b/tests/printer/expr/expected/binary.res.txt index 7b8bf4c9..2ab41084 100644 --- a/tests/printer/expr/expected/binary.res.txt +++ b/tests/printer/expr/expected/binary.res.txt @@ -481,9 +481,9 @@ foo := ) |> Array.of_list |> ReasonReact.array}
let aggregateTotal = (forecast, ~audienceType) => - Js.Nullable.toOption(forecast["audiences"]) - ->Option.flatMap(item => Js.Dict.get(item, audienceType)) - ->Option.map(item => { + Js.Nullable.toOption(forecast["audiences"])->Option.flatMap(item => + Js.Dict.get(item, audienceType) + )->Option.map(item => { pages: item["reach"]["pages"], views: item["reach"]["views"], sample: item["reach"]["sample"], @@ -492,13 +492,13 @@ let aggregateTotal = (forecast, ~audienceType) => React.useEffect4(() => { switch (context.library, context.account) { | (Some(library), Some(account)) => - library.getBalance(. account) - ->Promise.Js.catch(_ => {Promise.resolved(None)}) - ->Promise.get(newBalance => { - dispatch(LoadAddress(account, newBalance->Belt.Option.flatMap(balance => - Eth.make(balance.toString(.)) - ))) - }) + library.getBalance(. account)->Promise.Js.catch(_ => {Promise.resolved(None)})->Promise.get( + newBalance => { + dispatch(LoadAddress(account, newBalance->Belt.Option.flatMap(balance => + Eth.make(balance.toString(.)) + ))) + }, + ) None | _ => None diff --git a/tests/printer/expr/expected/callback.res.txt b/tests/printer/expr/expected/callback.res.txt index 5282b929..e79ab130 100644 --- a/tests/printer/expr/expected/callback.res.txt +++ b/tests/printer/expr/expected/callback.res.txt @@ -179,17 +179,13 @@ foo(list => list()) foo(\"switch" => \"switch"()) // the [] of the array should break -[ - fn(x => { +[fn(x => { let _ = x - }), - fn(y => { + }), fn(y => { let _ = y - }), - fn(z => { + }), fn(z => { let _ = z - }), -] + })] // similar, the jsx tree should be broken over multiple lines let f = () => { @@ -200,13 +196,9 @@ let f = () => { | Done(Error(_)) => "Error"->React.string | Done(Ok(users)) => <> -
    - {users - ->Array.map(user => { +
      {users->Array.map(user => {
    • {user.username->React.string}
    • - }) - ->React.array} -
    + })->React.array}
{reloadableUser.last->AsyncData.isLoading ? "Loading next page"->React.string : React.null} @@ -225,10 +217,9 @@ myPromise->Js.Promise.then_(value => { Js.Promise.resolve(-2) }, _) -let decoratorTags = - items - ->Js.Array2.filter(items => {items.category === Decorators}) - ->Belt.Array.map(item => { +let decoratorTags = items->Js.Array2.filter(items => { + items.category === Decorators + })->Belt.Array.map(item => { diff --git a/tests/printer/expr/expected/let.res.txt b/tests/printer/expr/expected/let.res.txt index 879efc28..fd1f0bb6 100644 --- a/tests/printer/expr/expected/let.res.txt +++ b/tests/printer/expr/expected/let.res.txt @@ -47,11 +47,7 @@ let f = x => { ->Option.flatMap(Js.Json.decodeString) ->Option.map(Js.Date.fromString) - let b = - x - ->Js.Dict.get("wm-property") - ->Option.flatMap(Js.Json.decodeString) - ->Option.flatMap(x => + let b = x->Js.Dict.get("wm-property")->Option.flatMap(Js.Json.decodeString)->Option.flatMap(x => switch x { | "like-of" => Some(#like) | "repost-of" => Some(#repost)