@@ -47928,7 +47928,7 @@ let funExpr expr =
47928
47928
collectNewTypes (stringLoc :: acc) returnExpr
47929
47929
| returnExpr -> (List.rev acc, returnExpr)
47930
47930
in
47931
- let rec collect attrsBefore acc expr =
47931
+ let rec collect n attrsBefore acc expr =
47932
47932
match expr with
47933
47933
| {
47934
47934
pexp_desc =
@@ -47944,13 +47944,17 @@ let funExpr expr =
47944
47944
pexp_attributes = [];
47945
47945
} ->
47946
47946
let parameter = Parameter {attrs = []; lbl; defaultExpr; pat = pattern} in
47947
- collect attrsBefore (parameter :: acc) returnExpr
47947
+ collect (n + 1) attrsBefore (parameter :: acc) returnExpr
47948
47948
| {pexp_desc = Pexp_newtype (stringLoc, rest); pexp_attributes = attrs} ->
47949
47949
let stringLocs, returnExpr = collectNewTypes [stringLoc] rest in
47950
47950
let param = NewTypes {attrs; locs = stringLocs} in
47951
- collect attrsBefore (param :: acc) returnExpr
47952
- | {pexp_desc = Pexp_fun _; pexp_attributes = [({txt = "bs"}, _)]} ->
47953
- (* stop here, the uncurried attribute always indicates the beginning of an arrow function
47951
+ collect (n + 1) attrsBefore (param :: acc) returnExpr
47952
+ | {pexp_desc = Pexp_fun _; pexp_attributes}
47953
+ when pexp_attributes
47954
+ |> List.exists (fun ({Location.txt}, _) ->
47955
+ txt = "bs" || txt = "res.async")
47956
+ && n > 0 ->
47957
+ (* stop here, the uncurried or async attribute always indicates the beginning of an arrow function
47954
47958
* e.g. `(. a) => (. b)` instead of `(. a, . b)` *)
47955
47959
(attrsBefore, List.rev acc, expr)
47956
47960
| {
@@ -47959,17 +47963,24 @@ let funExpr expr =
47959
47963
(((Labelled _ | Optional _) as lbl), defaultExpr, pattern, returnExpr);
47960
47964
pexp_attributes = attrs;
47961
47965
} ->
47962
- let parameter = Parameter {attrs; lbl; defaultExpr; pat = pattern} in
47963
- collect attrsBefore (parameter :: acc) returnExpr
47966
+ (* Normally attributes are attached to the labelled argument, e.g. (@foo ~x) => ...
47967
+ In the case of `@res.async`, pass the attribute to the outside *)
47968
+ let attrs_async, attrs_other =
47969
+ attrs |> List.partition (fun ({Location.txt}, _) -> txt = "res.async")
47970
+ in
47971
+ let parameter =
47972
+ Parameter {attrs = attrs_other; lbl; defaultExpr; pat = pattern}
47973
+ in
47974
+ collect (n + 1) (attrs_async @ attrsBefore) (parameter :: acc) returnExpr
47964
47975
| expr -> (attrsBefore, List.rev acc, expr)
47965
47976
in
47966
47977
match expr with
47967
47978
| {
47968
47979
pexp_desc = Pexp_fun (Nolabel, _defaultExpr, _pattern, _returnExpr);
47969
47980
pexp_attributes = attrs;
47970
47981
} as expr ->
47971
- collect attrs [] {expr with pexp_attributes = []}
47972
- | expr -> collect [] [] expr
47982
+ collect 0 attrs [] {expr with pexp_attributes = []}
47983
+ | expr -> collect 0 [] [] expr
47973
47984
47974
47985
let processBracesAttr expr =
47975
47986
match expr.pexp_attributes with
@@ -51398,6 +51409,11 @@ let hasCommentsInside tbl loc =
51398
51409
| None -> false
51399
51410
| _ -> true
51400
51411
51412
+ let hasTrailingComments tbl loc =
51413
+ match Hashtbl.find_opt tbl.CommentTable.trailing loc with
51414
+ | None -> false
51415
+ | _ -> true
51416
+
51401
51417
let printMultilineCommentContent txt =
51402
51418
(* Turns
51403
51419
* |* first line
@@ -54879,14 +54895,29 @@ and printBinaryExpression ~customLayout (expr : Parsetree.expression) cmtTbl =
54879
54895
| [] -> doc
54880
54896
| _ -> addParens doc
54881
54897
in
54898
+ let isAwait =
54899
+ ParsetreeViewer.hasAwaitAttribute expr.pexp_attributes
54900
+ in
54882
54901
let doc =
54883
- Doc.concat
54884
- [
54885
- leftPrinted;
54886
- printBinaryOperator ~inlineRhs:false operator;
54887
- rightPrinted;
54888
- ]
54902
+ if isAwait then
54903
+ Doc.concat
54904
+ [
54905
+ Doc.text "await ";
54906
+ Doc.lparen;
54907
+ leftPrinted;
54908
+ printBinaryOperator ~inlineRhs:false operator;
54909
+ rightPrinted;
54910
+ Doc.rparen;
54911
+ ]
54912
+ else
54913
+ Doc.concat
54914
+ [
54915
+ leftPrinted;
54916
+ printBinaryOperator ~inlineRhs:false operator;
54917
+ rightPrinted;
54918
+ ]
54889
54919
in
54920
+
54890
54921
let doc =
54891
54922
if (not isLhs) && Parens.rhsBinaryExprOperand operator expr then
54892
54923
Doc.concat [Doc.lparen; doc; Doc.rparen]
@@ -55321,8 +55352,17 @@ and printJsxExpression ~customLayout lident args cmtTbl =
55321
55352
Pexp_construct ({txt = Longident.Lident "[]"}, None);
55322
55353
}
55323
55354
when isSelfClosing ->
55324
- Doc.concat [Doc.line; Doc.text "/>"]
55325
- | _ -> Doc.concat [Doc.softLine; Doc.greaterThan]);
55355
+ Doc.text "/>"
55356
+ | _ ->
55357
+ (* if tag A has trailing comments then put > on the next line
55358
+ <A
55359
+ // comments
55360
+ >
55361
+ </A>
55362
+ *)
55363
+ if hasTrailingComments cmtTbl lident.Asttypes.loc then
55364
+ Doc.concat [Doc.softLine; Doc.greaterThan]
55365
+ else Doc.greaterThan);
55326
55366
]);
55327
55367
(if isSelfClosing then Doc.nil
55328
55368
else
@@ -55420,6 +55460,27 @@ and printJsxChildren ~customLayout (childrenExpr : Parsetree.expression) ~sep
55420
55460
55421
55461
and printJsxProps ~customLayout args cmtTbl :
55422
55462
Doc.t * Parsetree.expression option =
55463
+ (* This function was introduced because we have different formatting behavior for self-closing tags and other tags
55464
+ we always put /> on a new line for self-closing tag when it breaks
55465
+ <A
55466
+ a=""
55467
+ />
55468
+
55469
+ <A
55470
+ a="">
55471
+ <B />
55472
+ </A>
55473
+ we should remove this function once the format is unified
55474
+ *)
55475
+ let isSelfClosing children =
55476
+ match children with
55477
+ | {
55478
+ Parsetree.pexp_desc = Pexp_construct ({txt = Longident.Lident "[]"}, None);
55479
+ pexp_loc = loc;
55480
+ } ->
55481
+ not (hasCommentsInside cmtTbl loc)
55482
+ | _ -> false
55483
+ in
55423
55484
let rec loop props args =
55424
55485
match args with
55425
55486
| [] -> (Doc.nil, None)
@@ -55431,13 +55492,42 @@ and printJsxProps ~customLayout args cmtTbl :
55431
55492
Pexp_construct ({txt = Longident.Lident "()"}, None);
55432
55493
} );
55433
55494
] ->
55495
+ let doc = if isSelfClosing children then Doc.line else Doc.nil in
55496
+ (doc, Some children)
55497
+ | ((_, expr) as lastProp)
55498
+ :: [
55499
+ (Asttypes.Labelled "children", children);
55500
+ ( Asttypes.Nolabel,
55501
+ {
55502
+ Parsetree.pexp_desc =
55503
+ Pexp_construct ({txt = Longident.Lident "()"}, None);
55504
+ } );
55505
+ ] ->
55506
+ let loc =
55507
+ match expr.Parsetree.pexp_attributes with
55508
+ | ({Location.txt = "ns.namedArgLoc"; loc}, _) :: _attrs ->
55509
+ {loc with loc_end = expr.pexp_loc.loc_end}
55510
+ | _ -> expr.pexp_loc
55511
+ in
55512
+ let trailingCommentsPresent = hasTrailingComments cmtTbl loc in
55513
+ let propDoc = printJsxProp ~customLayout lastProp cmtTbl in
55434
55514
let formattedProps =
55435
- Doc.indent
55436
- (match props with
55437
- | [] -> Doc.nil
55438
- | props ->
55439
- Doc.concat
55440
- [Doc.line; Doc.group (Doc.join ~sep:Doc.line (props |> List.rev))])
55515
+ Doc.concat
55516
+ [
55517
+ Doc.indent
55518
+ (Doc.concat
55519
+ [
55520
+ Doc.line;
55521
+ Doc.group
55522
+ (Doc.join ~sep:Doc.line (propDoc :: props |> List.rev));
55523
+ ]);
55524
+ (* print > on new line if the last prop has trailing comments *)
55525
+ (match (isSelfClosing children, trailingCommentsPresent) with
55526
+ (* we always put /> on a new line when a self-closing tag breaks *)
55527
+ | true, _ -> Doc.line
55528
+ | false, true -> Doc.softLine
55529
+ | false, false -> Doc.nil);
55530
+ ]
55441
55531
in
55442
55532
(formattedProps, Some children)
55443
55533
| arg :: args ->
@@ -55978,7 +56068,7 @@ and printExprFunParameters ~customLayout ~inCallback ~async ~uncurried
55978
56068
let txtDoc =
55979
56069
let var = printIdentLike stringLoc.txt in
55980
56070
let var = if hasConstraint then addParens var else var in
55981
- if async then addAsync (Doc.concat [Doc.lparen; var; Doc.rparen]) else var
56071
+ if async then addAsync var else var
55982
56072
in
55983
56073
printComments txtDoc cmtTbl stringLoc.loc
55984
56074
(* let f = () => () *)
0 commit comments