From 5751f570a2e7f8f060bd6e15d6e879fcc4af8bc9 Mon Sep 17 00:00:00 2001 From: nojaf Date: Mon, 31 Mar 2025 21:11:48 +0200 Subject: [PATCH 1/2] Initial Pexp_braces --- analysis/src/CompletionExpressions.ml | 2 +- analysis/src/Utils.ml | 4 +- analysis/src/Xform.ml | 74 +-- compiler/frontend/bs_ast_mapper.ml | 1 + compiler/ml/ast_helper.ml | 1 + compiler/ml/ast_helper.mli | 1 + compiler/ml/ast_iterator.ml | 1 + compiler/ml/ast_mapper.ml | 1 + compiler/ml/ast_mapper_from0.ml | 316 ++++++----- compiler/ml/ast_mapper_to0.ml | 8 + compiler/ml/depend.ml | 1 + compiler/ml/parsetree.ml | 6 +- compiler/ml/pprintast.ml | 1 + compiler/ml/printast.ml | 3 + compiler/ml/typecore.ml | 4 + compiler/syntax/src/res_ast_debugger.ml | 2 + compiler/syntax/src/res_comments_table.ml | 13 +- compiler/syntax/src/res_core.ml | 53 +- compiler/syntax/src/res_parens.ml | 561 +++++++++---------- compiler/syntax/src/res_parsetree_viewer.ml | 25 +- compiler/syntax/src/res_parsetree_viewer.mli | 3 - compiler/syntax/src/res_printer.ml | 63 +-- 22 files changed, 560 insertions(+), 584 deletions(-) diff --git a/analysis/src/CompletionExpressions.ml b/analysis/src/CompletionExpressions.ml index e5858d1ee6..eb62d98b30 100644 --- a/analysis/src/CompletionExpressions.ml +++ b/analysis/src/CompletionExpressions.ml @@ -15,7 +15,7 @@ let rec traverseExpr (exp : Parsetree.expression) ~exprPath ~pos let locHasCursor loc = loc |> CursorPosition.locHasCursor ~pos in let someIfHasCursor v = if locHasCursor exp.pexp_loc then Some v else None in match exp.pexp_desc with - | Pexp_ident {txt = Lident txt} when Utils.hasBraces exp.pexp_attributes -> + | Pexp_braces {pexp_desc = Pexp_ident {txt = Lident txt}} -> (* An ident with braces attribute corresponds to for example `{n}`. Looks like a record but is parsed as an ident with braces. *) someIfHasCursor (txt, [Completable.NRecordBody {seenFields = []}] @ exprPath) diff --git a/analysis/src/Utils.ml b/analysis/src/Utils.ml index c274b5a9fb..bda9dc3084 100644 --- a/analysis/src/Utils.ml +++ b/analysis/src/Utils.ml @@ -111,6 +111,7 @@ let identifyPexp pexp = | Pexp_pack _ -> "Pexp_pack" | Pexp_extension _ -> "Pexp_extension" | Pexp_open _ -> "Pexp_open" + | Pexp_braces _ -> "Pexp_braces" let identifyPpat pat = match pat with @@ -140,9 +141,6 @@ let rec skipWhite text i = | ' ' | '\n' | '\r' | '\t' -> skipWhite text (i - 1) | _ -> i -let hasBraces attributes = - attributes |> List.exists (fun (loc, _) -> loc.Location.txt = "res.braces") - let rec unwrapIfOption (t : Types.type_expr) = match t.desc with | Tlink t1 | Tsubst t1 | Tpoly (t1, []) -> unwrapIfOption t1 diff --git a/analysis/src/Xform.ml b/analysis/src/Xform.ml index 837f7df744..07435f3228 100644 --- a/analysis/src/Xform.ml +++ b/analysis/src/Xform.ml @@ -223,56 +223,62 @@ end module AddBracesToFn = struct (* Add braces to fn without braces *) - let mkIterator ~pos ~changed = + let map_structure ~pos ~(changed : Parsetree.structure) = (* While iterating the AST, keep info on which structure item we are in. Printing from the structure item, rather than the body of the function, gives better local pretty printing *) - let currentStructureItem = ref None in - - let structure_item (iterator : Ast_iterator.iterator) - (item : Parsetree.structure_item) = - let saved = !currentStructureItem in - currentStructureItem := Some item; - Ast_iterator.default_iterator.structure_item iterator item; - currentStructureItem := saved + let did_map = ref false in + let current_structure = ref None in + let structure_item (mapper : Ast_mapper.mapper) + (structure_item : Parsetree.structure_item) = + if !did_map then structure_item + else ( + current_structure := Some structure_item; + mapper.structure_item mapper structure_item) in - let expr (iterator : Ast_iterator.iterator) (e : Parsetree.expression) = - let bracesAttribute = - let loc = - { - Location.none with - loc_start = Lexing.dummy_pos; - loc_end = - { - Lexing.dummy_pos with - pos_lnum = Lexing.dummy_pos.pos_lnum + 1 (* force line break *); - }; - } - in - (Location.mkloc "res.braces" loc, Parsetree.PStr []) + let expr (mapper : Ast_mapper.mapper) (e : Parsetree.expression) = + let braces_loc = + { + Location.none with + loc_start = Lexing.dummy_pos; + loc_end = + { + Lexing.dummy_pos with + pos_lnum = Lexing.dummy_pos.pos_lnum + 1 (* force line break *); + }; + } in let isFunction = function | {Parsetree.pexp_desc = Pexp_fun _} -> true | _ -> false in - (match e.pexp_desc with - | Pexp_fun {rhs = bodyExpr} + match e.pexp_desc with + | Pexp_fun ({rhs = bodyExpr} as f) when Loc.hasPos ~pos bodyExpr.pexp_loc && isBracedExpr bodyExpr = false && isFunction bodyExpr = false -> - bodyExpr.pexp_attributes <- bracesAttribute :: bodyExpr.pexp_attributes; - changed := !currentStructureItem - | _ -> ()); - Ast_iterator.default_iterator.expr iterator e + did_map := true; + { + e with + pexp_desc = + Pexp_fun + {f with rhs = Ast_helper.Exp.braces ~loc:braces_loc bodyExpr}; + } + | _ -> mapper.expr mapper e in - {Ast_iterator.default_iterator with expr; structure_item} + let mapper = {Ast_mapper.default_mapper with expr; structure_item} in + let rec visit structure = + match structure with + | [] -> None + | x :: xs -> + let mapped = mapper.structure_item mapper x in + if !did_map then Some mapped else visit xs + in + visit changed let xform ~pos ~codeActions ~path ~printStructureItem structure = - let changed = ref None in - let iterator = mkIterator ~pos ~changed in - iterator.structure iterator structure; - match !changed with + match map_structure ~pos ~changed:structure with | None -> () | Some newStructureItem -> let range = Loc.rangeOfLoc newStructureItem.pstr_loc in diff --git a/compiler/frontend/bs_ast_mapper.ml b/compiler/frontend/bs_ast_mapper.ml index 4bcda7c534..76d1c29e9b 100644 --- a/compiler/frontend/bs_ast_mapper.ml +++ b/compiler/frontend/bs_ast_mapper.ml @@ -299,6 +299,7 @@ module E = struct let loc = sub.location sub loc in let attrs = sub.attributes sub attrs in match desc with + | Pexp_braces inner -> braces ~loc ~attrs (sub.expr sub inner) | Pexp_ident x -> ident ~loc ~attrs (map_loc sub x) | Pexp_constant x -> constant ~loc ~attrs x | Pexp_let (r, vbs, e) -> diff --git a/compiler/ml/ast_helper.ml b/compiler/ml/ast_helper.ml index aa0c66dbfc..a29d1a08cf 100644 --- a/compiler/ml/ast_helper.ml +++ b/compiler/ml/ast_helper.ml @@ -180,6 +180,7 @@ module Exp = struct let pack ?loc ?attrs a = mk ?loc ?attrs (Pexp_pack a) let open_ ?loc ?attrs a b c = mk ?loc ?attrs (Pexp_open (a, b, c)) let extension ?loc ?attrs a = mk ?loc ?attrs (Pexp_extension a) + let braces ?loc ?attrs a = mk ?loc ?attrs (Pexp_braces a) let case lhs ?guard rhs = {pc_lhs = lhs; pc_guard = guard; pc_rhs = rhs} end diff --git a/compiler/ml/ast_helper.mli b/compiler/ml/ast_helper.mli index a78e33589e..2b46fc12b9 100644 --- a/compiler/ml/ast_helper.mli +++ b/compiler/ml/ast_helper.mli @@ -208,6 +208,7 @@ module Exp : sig val open_ : ?loc:loc -> ?attrs:attrs -> override_flag -> lid -> expression -> expression val extension : ?loc:loc -> ?attrs:attrs -> extension -> expression + val braces : ?loc:loc -> ?attrs:attrs -> expression -> expression val case : pattern -> ?guard:expression -> expression -> case end diff --git a/compiler/ml/ast_iterator.ml b/compiler/ml/ast_iterator.ml index 1c0bd087da..fc6fd0dd61 100644 --- a/compiler/ml/ast_iterator.ml +++ b/compiler/ml/ast_iterator.ml @@ -273,6 +273,7 @@ module E = struct sub.location sub loc; sub.attributes sub attrs; match desc with + | Pexp_braces e -> sub.expr sub e | Pexp_ident x -> iter_loc sub x | Pexp_constant _ -> () | Pexp_let (_r, vbs, e) -> diff --git a/compiler/ml/ast_mapper.ml b/compiler/ml/ast_mapper.ml index f2055efb93..3299b3f64a 100644 --- a/compiler/ml/ast_mapper.ml +++ b/compiler/ml/ast_mapper.ml @@ -270,6 +270,7 @@ module E = struct let loc = sub.location sub loc in let attrs = sub.attributes sub attrs in match desc with + | Pexp_braces inner -> braces ~loc ~attrs (sub.expr sub inner) | Pexp_ident x -> ident ~loc ~attrs (map_loc sub x) | Pexp_constant x -> constant ~loc ~attrs x | Pexp_let (r, vbs, e) -> diff --git a/compiler/ml/ast_mapper_from0.ml b/compiler/ml/ast_mapper_from0.ml index 1e3e3687b7..47c6fa9e8d 100644 --- a/compiler/ml/ast_mapper_from0.ml +++ b/compiler/ml/ast_mapper_from0.ml @@ -295,153 +295,187 @@ end module E = struct (* Value expressions for the core language *) - let map sub {pexp_loc = loc; pexp_desc = desc; pexp_attributes = attrs} = + let map sub {pexp_loc = loc; pexp_desc = desc; pexp_attributes = attrs0} = let open Exp in let loc = sub.location sub loc in - let attrs = sub.attributes sub attrs in - match desc with - | Pexp_ident x -> ident ~loc ~attrs (map_loc sub x) - | Pexp_constant x -> constant ~loc ~attrs (map_constant x) - | Pexp_let (r, vbs, e) -> - let_ ~loc ~attrs r (List.map (sub.value_binding sub) vbs) (sub.expr sub e) - | Pexp_fun (lab, def, p, e) -> - let lab = Asttypes.to_arg_label lab in - let async = Ext_list.exists attrs (fun ({txt}, _) -> txt = "res.async") in - fun_ ~loc ~attrs ~async ~arity:None lab - (map_opt (sub.expr sub) def) - (sub.pat sub p) (sub.expr sub e) - | Pexp_function _ -> assert false - | Pexp_apply (e, l) -> - let e = - match (e.pexp_desc, l) with - | ( Pexp_ident ({txt = Longident.Lident "|."} as lid), - [(Nolabel, _); (Nolabel, _)] ) -> - {e with pexp_desc = Pexp_ident {lid with txt = Longident.Lident "->"}} - | ( Pexp_ident ({txt = Longident.Lident "^"} as lid), - [(Nolabel, _); (Nolabel, _)] ) -> - {e with pexp_desc = Pexp_ident {lid with txt = Longident.Lident "++"}} - | ( Pexp_ident ({txt = Longident.Lident "<>"} as lid), - [(Nolabel, _); (Nolabel, _)] ) -> - {e with pexp_desc = Pexp_ident {lid with txt = Longident.Lident "!="}} - | ( Pexp_ident ({txt = Longident.Lident "!="} as lid), - [(Nolabel, _); (Nolabel, _)] ) -> - { - e with - pexp_desc = Pexp_ident {lid with txt = Longident.Lident "!=="}; - } - | ( Pexp_ident ({txt = Longident.Lident "="} as lid), - [(Nolabel, _); (Nolabel, _)] ) -> - {e with pexp_desc = Pexp_ident {lid with txt = Longident.Lident "=="}} - | ( Pexp_ident ({txt = Longident.Lident "=="} as lid), - [(Nolabel, _); (Nolabel, _)] ) -> - { - e with - pexp_desc = Pexp_ident {lid with txt = Longident.Lident "==="}; - } - | _ -> e + let attrs = sub.attributes sub attrs0 in + if List.exists (fun ({txt}, _) -> txt = "res.braces") attrs then + let braces_loc = + List.find (fun ({txt}, _) -> txt = "res.braces") attrs + |> fun ({loc}, _) -> loc in - let process_partial_app_attribute attrs = - let rec process partial_app acc attrs = - match attrs with - | [] -> (partial_app, List.rev acc) - | ({Location.txt = "res.partial"}, _) :: rest -> process true acc rest - | attr :: rest -> process partial_app (attr :: acc) rest - in - process false [] attrs + let inner_attrs = + List.filter (fun ({txt}, _) -> txt <> "res.braces") attrs0 in - let partial, attrs = process_partial_app_attribute attrs in - apply ~loc ~attrs ~partial (sub.expr sub e) - (List.map - (fun (lbl, e) -> (Asttypes.to_arg_label lbl, sub.expr sub e)) - l) - | Pexp_match (e, pel) -> - match_ ~loc ~attrs (sub.expr sub e) (sub.cases sub pel) - | Pexp_try (e, pel) -> try_ ~loc ~attrs (sub.expr sub e) (sub.cases sub pel) - | Pexp_tuple el -> tuple ~loc ~attrs (List.map (sub.expr sub) el) - | Pexp_construct (lid, arg) -> ( - let lid1 = map_loc sub lid in - let arg1 = map_opt (sub.expr sub) arg in - let exp1 = construct ~loc ~attrs lid1 arg1 in - match lid.txt with - | Lident "Function$" -> ( - let rec attributes_to_arity (attrs : Parsetree.attributes) = - match attrs with - | ( {txt = "res.arity"}, - PStr - [ - { - pstr_desc = - Pstr_eval - ( {pexp_desc = Pexp_constant (Pconst_integer (arity, _))}, - _ ); - }; - ] ) - :: _ -> - int_of_string arity - | _ :: rest -> attributes_to_arity rest - | [] -> assert false + Ast_helper.Exp.braces ~loc:braces_loc + (sub.expr sub + {pexp_loc = loc; pexp_desc = desc; pexp_attributes = inner_attrs}) + else + match desc with + | Pexp_ident x -> ident ~loc ~attrs (map_loc sub x) + | Pexp_constant x -> constant ~loc ~attrs (map_constant x) + | Pexp_let (r, vbs, e) -> + let_ ~loc ~attrs r + (List.map (sub.value_binding sub) vbs) + (sub.expr sub e) + | Pexp_fun (lab, def, p, e) -> + let lab = Asttypes.to_arg_label lab in + let async = + Ext_list.exists attrs (fun ({txt}, _) -> txt = "res.async") + in + fun_ ~loc ~attrs ~async ~arity:None lab + (map_opt (sub.expr sub) def) + (sub.pat sub p) (sub.expr sub e) + | Pexp_function _ -> assert false + | Pexp_apply (e, l) -> + let e = + match (e.pexp_desc, l) with + | ( Pexp_ident ({txt = Longident.Lident "|."} as lid), + [(Nolabel, _); (Nolabel, _)] ) -> + { + e with + pexp_desc = Pexp_ident {lid with txt = Longident.Lident "->"}; + } + | ( Pexp_ident ({txt = Longident.Lident "^"} as lid), + [(Nolabel, _); (Nolabel, _)] ) -> + { + e with + pexp_desc = Pexp_ident {lid with txt = Longident.Lident "++"}; + } + | ( Pexp_ident ({txt = Longident.Lident "<>"} as lid), + [(Nolabel, _); (Nolabel, _)] ) -> + { + e with + pexp_desc = Pexp_ident {lid with txt = Longident.Lident "!="}; + } + | ( Pexp_ident ({txt = Longident.Lident "!="} as lid), + [(Nolabel, _); (Nolabel, _)] ) -> + { + e with + pexp_desc = Pexp_ident {lid with txt = Longident.Lident "!=="}; + } + | ( Pexp_ident ({txt = Longident.Lident "="} as lid), + [(Nolabel, _); (Nolabel, _)] ) -> + { + e with + pexp_desc = Pexp_ident {lid with txt = Longident.Lident "=="}; + } + | ( Pexp_ident ({txt = Longident.Lident "=="} as lid), + [(Nolabel, _); (Nolabel, _)] ) -> + { + e with + pexp_desc = Pexp_ident {lid with txt = Longident.Lident "==="}; + } + | _ -> e in - match arg1 with - | Some ({pexp_desc = Pexp_fun f} as e1) -> - let arity = Some (attributes_to_arity attrs) in - {e1 with pexp_desc = Pexp_fun {f with arity}} + let process_partial_app_attribute attrs = + let rec process partial_app acc attrs = + match attrs with + | [] -> (partial_app, List.rev acc) + | ({Location.txt = "res.partial"}, _) :: rest -> + process true acc rest + | attr :: rest -> process partial_app (attr :: acc) rest + in + process false [] attrs + in + let partial, attrs = process_partial_app_attribute attrs in + apply ~loc ~attrs ~partial (sub.expr sub e) + (List.map + (fun (lbl, e) -> (Asttypes.to_arg_label lbl, sub.expr sub e)) + l) + | Pexp_match (e, pel) -> + match_ ~loc ~attrs (sub.expr sub e) (sub.cases sub pel) + | Pexp_try (e, pel) -> + try_ ~loc ~attrs (sub.expr sub e) (sub.cases sub pel) + | Pexp_tuple el -> tuple ~loc ~attrs (List.map (sub.expr sub) el) + | Pexp_construct (lid, arg) -> ( + let lid1 = map_loc sub lid in + let arg1 = map_opt (sub.expr sub) arg in + let exp1 = construct ~loc ~attrs lid1 arg1 in + match lid.txt with + | Lident "Function$" -> ( + let rec attributes_to_arity (attrs : Parsetree.attributes) = + match attrs with + | ( {txt = "res.arity"}, + PStr + [ + { + pstr_desc = + Pstr_eval + ( { + pexp_desc = + Pexp_constant (Pconst_integer (arity, _)); + }, + _ ); + }; + ] ) + :: _ -> + int_of_string arity + | _ :: rest -> attributes_to_arity rest + | [] -> assert false + in + match arg1 with + | Some ({pexp_desc = Pexp_fun f} as e1) -> + let arity = Some (attributes_to_arity attrs) in + {e1 with pexp_desc = Pexp_fun {f with arity}} + | _ -> exp1) | _ -> exp1) - | _ -> exp1) - | Pexp_variant (lab, eo) -> - variant ~loc ~attrs lab (map_opt (sub.expr sub) eo) - | Pexp_record (l, eo) -> - record ~loc ~attrs - (Ext_list.map l (fun (lid, e) -> - let lid1 = map_loc sub lid in - let e1 = sub.expr sub e in - let optional, attrs = - Parsetree0.get_optional_attr e1.pexp_attributes - in - (lid1, {e1 with pexp_attributes = attrs}, optional))) - (map_opt (sub.expr sub) eo) - | Pexp_field (e, lid) -> - field ~loc ~attrs (sub.expr sub e) (map_loc sub lid) - | Pexp_setfield (e1, lid, e2) -> - setfield ~loc ~attrs (sub.expr sub e1) (map_loc sub lid) (sub.expr sub e2) - | Pexp_array el -> array ~loc ~attrs (List.map (sub.expr sub) el) - | Pexp_ifthenelse (e1, e2, e3) -> - ifthenelse ~loc ~attrs (sub.expr sub e1) (sub.expr sub e2) - (map_opt (sub.expr sub) e3) - | Pexp_sequence (e1, e2) -> - sequence ~loc ~attrs (sub.expr sub e1) (sub.expr sub e2) - | Pexp_while (e1, e2) -> - while_ ~loc ~attrs (sub.expr sub e1) (sub.expr sub e2) - | Pexp_for (p, e1, e2, d, e3) -> - for_ ~loc ~attrs (sub.pat sub p) (sub.expr sub e1) (sub.expr sub e2) d - (sub.expr sub e3) - | Pexp_coerce (e, (), t2) -> - coerce ~loc ~attrs (sub.expr sub e) (sub.typ sub t2) - | Pexp_constraint (e, t) -> - constraint_ ~loc ~attrs (sub.expr sub e) (sub.typ sub t) - | Pexp_send (e, s) -> send ~loc ~attrs (sub.expr sub e) (map_loc sub s) - | Pexp_new _ -> failwith "Pexp_new is no longer present in ReScript" - | Pexp_setinstvar _ -> - failwith "Pexp_setinstvar is no longer present in ReScript" - | Pexp_override _ -> - failwith "Pexp_override is no longer present in ReScript" - | Pexp_letmodule (s, me, e) -> - letmodule ~loc ~attrs (map_loc sub s) (sub.module_expr sub me) - (sub.expr sub e) - | Pexp_letexception (cd, e) -> - letexception ~loc ~attrs - (sub.extension_constructor sub cd) - (sub.expr sub e) - | Pexp_assert e -> assert_ ~loc ~attrs (sub.expr sub e) - | Pexp_lazy e -> lazy_ ~loc ~attrs (sub.expr sub e) - | Pexp_poly _ -> failwith "Pexp_poly is no longer present in ReScript" - | Pexp_object () -> assert false - | Pexp_newtype (s, e) -> - newtype ~loc ~attrs (map_loc sub s) (sub.expr sub e) - | Pexp_pack me -> pack ~loc ~attrs (sub.module_expr sub me) - | Pexp_open (ovf, lid, e) -> - open_ ~loc ~attrs ovf (map_loc sub lid) (sub.expr sub e) - | Pexp_extension x -> extension ~loc ~attrs (sub.extension sub x) - | Pexp_unreachable -> assert false + | Pexp_variant (lab, eo) -> + variant ~loc ~attrs lab (map_opt (sub.expr sub) eo) + | Pexp_record (l, eo) -> + record ~loc ~attrs + (Ext_list.map l (fun (lid, e) -> + let lid1 = map_loc sub lid in + let e1 = sub.expr sub e in + let optional, attrs = + Parsetree0.get_optional_attr e1.pexp_attributes + in + (lid1, {e1 with pexp_attributes = attrs}, optional))) + (map_opt (sub.expr sub) eo) + | Pexp_field (e, lid) -> + field ~loc ~attrs (sub.expr sub e) (map_loc sub lid) + | Pexp_setfield (e1, lid, e2) -> + setfield ~loc ~attrs (sub.expr sub e1) (map_loc sub lid) + (sub.expr sub e2) + | Pexp_array el -> array ~loc ~attrs (List.map (sub.expr sub) el) + | Pexp_ifthenelse (e1, e2, e3) -> + ifthenelse ~loc ~attrs (sub.expr sub e1) (sub.expr sub e2) + (map_opt (sub.expr sub) e3) + | Pexp_sequence (e1, e2) -> + sequence ~loc ~attrs (sub.expr sub e1) (sub.expr sub e2) + | Pexp_while (e1, e2) -> + while_ ~loc ~attrs (sub.expr sub e1) (sub.expr sub e2) + | Pexp_for (p, e1, e2, d, e3) -> + for_ ~loc ~attrs (sub.pat sub p) (sub.expr sub e1) (sub.expr sub e2) d + (sub.expr sub e3) + | Pexp_coerce (e, (), t2) -> + coerce ~loc ~attrs (sub.expr sub e) (sub.typ sub t2) + | Pexp_constraint (e, t) -> + constraint_ ~loc ~attrs (sub.expr sub e) (sub.typ sub t) + | Pexp_send (e, s) -> send ~loc ~attrs (sub.expr sub e) (map_loc sub s) + | Pexp_new _ -> failwith "Pexp_new is no longer present in ReScript" + | Pexp_setinstvar _ -> + failwith "Pexp_setinstvar is no longer present in ReScript" + | Pexp_override _ -> + failwith "Pexp_override is no longer present in ReScript" + | Pexp_letmodule (s, me, e) -> + letmodule ~loc ~attrs (map_loc sub s) (sub.module_expr sub me) + (sub.expr sub e) + | Pexp_letexception (cd, e) -> + letexception ~loc ~attrs + (sub.extension_constructor sub cd) + (sub.expr sub e) + | Pexp_assert e -> assert_ ~loc ~attrs (sub.expr sub e) + | Pexp_lazy e -> lazy_ ~loc ~attrs (sub.expr sub e) + | Pexp_poly _ -> failwith "Pexp_poly is no longer present in ReScript" + | Pexp_object () -> assert false + | Pexp_newtype (s, e) -> + newtype ~loc ~attrs (map_loc sub s) (sub.expr sub e) + | Pexp_pack me -> pack ~loc ~attrs (sub.module_expr sub me) + | Pexp_open (ovf, lid, e) -> + open_ ~loc ~attrs ovf (map_loc sub lid) (sub.expr sub e) + | Pexp_extension x -> extension ~loc ~attrs (sub.extension sub x) + | Pexp_unreachable -> assert false end module P = struct diff --git a/compiler/ml/ast_mapper_to0.ml b/compiler/ml/ast_mapper_to0.ml index cc343762fc..203e45f7ab 100644 --- a/compiler/ml/ast_mapper_to0.ml +++ b/compiler/ml/ast_mapper_to0.ml @@ -407,6 +407,14 @@ module E = struct | Pexp_open (ovf, lid, e) -> open_ ~loc ~attrs ovf (map_loc sub lid) (sub.expr sub e) | Pexp_extension x -> extension ~loc ~attrs (sub.extension sub x) + | Pexp_braces inner -> + let mapped_inner = sub.expr sub inner in + { + mapped_inner with + pexp_attributes = + (Location.mkloc "res.braces" loc, Parsetree0.PStr []) + :: mapped_inner.pexp_attributes; + } end module P = struct diff --git a/compiler/ml/depend.ml b/compiler/ml/depend.ml index f33454d448..dce8e6aff6 100644 --- a/compiler/ml/depend.ml +++ b/compiler/ml/depend.ml @@ -213,6 +213,7 @@ let add_pattern bv pat = let rec add_expr bv exp = match exp.pexp_desc with + | Pexp_braces e -> add_expr bv e | Pexp_ident l -> add bv l | Pexp_constant _ -> () | Pexp_let (rf, pel, e) -> diff --git a/compiler/ml/parsetree.ml b/compiler/ml/parsetree.ml index b7db5e902b..6a7949f0dc 100644 --- a/compiler/ml/parsetree.ml +++ b/compiler/ml/parsetree.ml @@ -313,8 +313,10 @@ and expression_desc = let open M in E let! open M in E *) | Pexp_extension of extension -(* [%id] *) -(* . *) + (* [%id] *) + (* . *) + | Pexp_braces of expression +(* expression wrapped in { } *) and case = { (* (P -> E) or (P when E0 -> E) *) diff --git a/compiler/ml/pprintast.ml b/compiler/ml/pprintast.ml index 31cb171d81..9984f88868 100644 --- a/compiler/ml/pprintast.ml +++ b/compiler/ml/pprintast.ml @@ -722,6 +722,7 @@ and expression ctxt f x = (expression ctxt) e | Pexp_variant (l, Some eo) -> pp f "@[<2>`%s@;%a@]" l (simple_expr ctxt) eo | Pexp_extension e -> extension ctxt f e + | Pexp_braces inner -> pp f "{%a}" (expression ctxt) inner | _ -> expression1 ctxt f x and expression1 ctxt f x = diff --git a/compiler/ml/printast.ml b/compiler/ml/printast.ml index 777829f0c9..36b8952940 100644 --- a/compiler/ml/printast.ml +++ b/compiler/ml/printast.ml @@ -345,6 +345,9 @@ and expression i ppf x = | Pexp_extension (s, arg) -> line i ppf "Pexp_extension \"%s\"\n" s.txt; payload i ppf arg + | Pexp_braces e -> + line i ppf "Pexp_braces\n"; + expression i ppf e and value_description i ppf x = line i ppf "value_description %a %a\n" fmt_string_loc x.pval_name fmt_location diff --git a/compiler/ml/typecore.ml b/compiler/ml/typecore.ml index 44bf252d3a..1bda428887 100644 --- a/compiler/ml/typecore.ml +++ b/compiler/ml/typecore.ml @@ -132,6 +132,7 @@ let iter_expression f e = let rec expr e = f e; match e.pexp_desc with + | Pexp_braces inner -> expr inner | Pexp_extension _ (* we don't iterate under extension point *) | Pexp_ident _ | Pexp_constant _ -> () @@ -2265,6 +2266,9 @@ and type_expect_ ?type_clash_context ?in_function ?(recarg = Rejected) env sexp else (id, ld, e, opt) in match sexp.pexp_desc with + | Pexp_braces inner -> + type_expect ?type_clash_context ?in_function ?recarg:(Some recarg) env inner + ty_expected | Pexp_ident lid -> let path, desc = Typetexp.find_value env lid.loc lid.txt in (if !Clflags.annotations then diff --git a/compiler/syntax/src/res_ast_debugger.ml b/compiler/syntax/src/res_ast_debugger.ml index a4d4f4a390..374f2d2f3a 100644 --- a/compiler/syntax/src/res_ast_debugger.ml +++ b/compiler/syntax/src/res_ast_debugger.ml @@ -707,6 +707,8 @@ module SexpAst = struct ] | Pexp_extension ext -> Sexp.list [Sexp.atom "Pexp_extension"; extension ext] + | Pexp_braces inner -> + Sexp.list [Sexp.atom "Pexp_braces"; expression inner] in Sexp.list [Sexp.atom "expression"; desc] diff --git a/compiler/syntax/src/res_comments_table.ml b/compiler/syntax/src/res_comments_table.ml index c003d04ff6..b3e080b20f 100644 --- a/compiler/syntax/src/res_comments_table.ml +++ b/compiler/syntax/src/res_comments_table.ml @@ -357,19 +357,10 @@ let get_loc node = let open Parsetree in match node with | Case case -> - { - case.pc_lhs.ppat_loc with - loc_end = - (match ParsetreeViewer.process_braces_attr case.pc_rhs with - | None, _ -> case.pc_rhs.pexp_loc.loc_end - | Some ({loc}, _), _ -> loc.Location.loc_end); - } + {case.pc_lhs.ppat_loc with loc_end = case.pc_rhs.pexp_loc.loc_end} | CoreType ct -> ct.ptyp_loc | ExprArgument {loc} -> loc - | Expression e -> ( - match e.pexp_attributes with - | ({txt = "res.braces" | "ns.braces"; loc}, _) :: _ -> loc - | _ -> e.pexp_loc) + | Expression e -> e.pexp_loc | ExprRecordRow (li, e) -> {li.loc with loc_end = e.pexp_loc.loc_end} | ExtensionConstructor ec -> ec.pext_loc | LabelDeclaration ld -> ld.pld_loc diff --git a/compiler/syntax/src/res_core.ml b/compiler/syntax/src/res_core.ml index d2f7bad50c..a619707bd3 100644 --- a/compiler/syntax/src/res_core.ml +++ b/compiler/syntax/src/res_core.ml @@ -166,7 +166,7 @@ let suppress_fragile_match_warning_attr = Ast_helper.Str.eval (Ast_helper.Exp.constant (Pconst_string ("-4", None))); ] ) -let make_braces_attr loc = (Location.mkloc "res.braces" loc, Parsetree.PStr []) + let template_literal_attr = (Location.mknoloc "res.template", Parsetree.PStr []) let make_pat_variant_spread_attr = (Location.mknoloc "res.patVariantSpread", Parsetree.PStr []) @@ -2888,22 +2888,16 @@ and parse_braced_or_record_expr p = let expr = parse_expr_block ~first:e p in Parser.expect Rbrace p; let loc = mk_loc start_pos p.prev_end_pos in - let braces = make_braces_attr loc in - { - expr with - Parsetree.pexp_attributes = braces :: expr.Parsetree.pexp_attributes; - } + Ast_helper.Exp.braces ~loc expr | Rbrace -> Parser.next p; let loc = mk_loc start_pos p.prev_end_pos in - let braces = make_braces_attr loc in - {e with pexp_attributes = braces :: e.pexp_attributes} + Ast_helper.Exp.braces ~loc e | _ -> let expr = parse_expr_block ~first:e p in Parser.expect Rbrace p; let loc = mk_loc start_pos p.prev_end_pos in - let braces = make_braces_attr loc in - {expr with pexp_attributes = braces :: expr.pexp_attributes})) + Ast_helper.Exp.braces ~loc expr)) | Question -> let expr = parse_record_expr ~start_pos [] p in Parser.expect Rbrace p; @@ -2921,8 +2915,7 @@ and parse_braced_or_record_expr p = let expr = parse_expr_block ~first:expr p in Parser.expect Rbrace p; let loc = mk_loc start_pos p.prev_end_pos in - let braces = make_braces_attr loc in - {expr with pexp_attributes = braces :: expr.pexp_attributes} + Ast_helper.Exp.braces ~loc expr | Uident _ | Lident _ -> ( let start_token = p.token in let value_or_constructor = parse_value_or_constructor p in @@ -2987,14 +2980,12 @@ and parse_braced_or_record_expr p = in Parser.expect Rbrace p; let loc = mk_loc start_pos p.prev_end_pos in - let braces = make_braces_attr loc in - {expr with pexp_attributes = braces :: expr.pexp_attributes} + Ast_helper.Exp.braces ~loc expr | Rbrace -> Parser.next p; let expr = Ast_helper.Exp.ident ~loc:path_ident.loc path_ident in let loc = mk_loc start_pos p.prev_end_pos in - let braces = make_braces_attr loc in - {expr with pexp_attributes = braces :: expr.pexp_attributes} + Ast_helper.Exp.braces ~loc expr | EqualGreater -> ( let loc = mk_loc start_pos ident_end_pos in let ident = Location.mkloc (Longident.last path_ident.txt) loc in @@ -3019,19 +3010,16 @@ and parse_braced_or_record_expr p = let expr = parse_expr_block ~first:e p in Parser.expect Rbrace p; let loc = mk_loc start_pos p.prev_end_pos in - let braces = make_braces_attr loc in - {expr with pexp_attributes = braces :: expr.pexp_attributes} + Ast_helper.Exp.braces ~loc expr | Rbrace -> Parser.next p; let loc = mk_loc start_pos p.prev_end_pos in - let braces = make_braces_attr loc in - {e with pexp_attributes = braces :: e.pexp_attributes} + Ast_helper.Exp.braces ~loc e | _ -> let expr = parse_expr_block ~first:e p in Parser.expect Rbrace p; let loc = mk_loc start_pos p.prev_end_pos in - let braces = make_braces_attr loc in - {expr with pexp_attributes = braces :: expr.pexp_attributes}) + Ast_helper.Exp.braces ~loc expr) | _ -> ( Parser.leave_breadcrumb p Grammar.ExprBlock; let a = @@ -3047,19 +3035,16 @@ and parse_braced_or_record_expr p = let expr = parse_expr_block ~first:e p in Parser.expect Rbrace p; let loc = mk_loc start_pos p.prev_end_pos in - let braces = make_braces_attr loc in - {expr with pexp_attributes = braces :: expr.pexp_attributes} + Ast_helper.Exp.braces ~loc expr | Rbrace -> Parser.next p; let loc = mk_loc start_pos p.prev_end_pos in - let braces = make_braces_attr loc in - {e with pexp_attributes = braces :: e.pexp_attributes} + Ast_helper.Exp.braces ~loc e | _ -> let expr = parse_expr_block ~first:e p in Parser.expect Rbrace p; let loc = mk_loc start_pos p.prev_end_pos in - let braces = make_braces_attr loc in - {expr with pexp_attributes = braces :: expr.pexp_attributes})) + Ast_helper.Exp.braces ~loc expr)) | _ -> ( Parser.leave_breadcrumb p Grammar.ExprBlock; let a = parse_primary_expr ~operand:value_or_constructor p in @@ -3071,25 +3056,21 @@ and parse_braced_or_record_expr p = let expr = parse_expr_block ~first:e p in Parser.expect Rbrace p; let loc = mk_loc start_pos p.prev_end_pos in - let braces = make_braces_attr loc in - {expr with pexp_attributes = braces :: expr.pexp_attributes} + Ast_helper.Exp.braces ~loc expr | Rbrace -> Parser.next p; let loc = mk_loc start_pos p.prev_end_pos in - let braces = make_braces_attr loc in - {e with pexp_attributes = braces :: e.pexp_attributes} + Ast_helper.Exp.braces ~loc e | _ -> let expr = parse_expr_block ~first:e p in Parser.expect Rbrace p; let loc = mk_loc start_pos p.prev_end_pos in - let braces = make_braces_attr loc in - {expr with pexp_attributes = braces :: expr.pexp_attributes})) + Ast_helper.Exp.braces ~loc expr)) | _ -> let expr = parse_expr_block p in Parser.expect Rbrace p; let loc = mk_loc start_pos p.prev_end_pos in - let braces = make_braces_attr loc in - {expr with pexp_attributes = braces :: expr.pexp_attributes} + Ast_helper.Exp.braces ~loc expr and parse_record_expr_row_with_string_key p = match p.Parser.token with diff --git a/compiler/syntax/src/res_parens.ml b/compiler/syntax/src/res_parens.ml index 8034e7cf59..7421ce8910 100644 --- a/compiler/syntax/src/res_parens.ml +++ b/compiler/syntax/src/res_parens.ml @@ -1,19 +1,16 @@ module ParsetreeViewer = Res_parsetree_viewer type kind = Parenthesized | Braced of Location.t | Nothing -let expr expr = - let opt_braces, _ = ParsetreeViewer.process_braces_attr expr in - match opt_braces with - | Some ({Location.loc = braces_loc}, _) -> Braced braces_loc - | _ -> ( - match expr with - | { - Parsetree.pexp_desc = - Pexp_constraint ({pexp_desc = Pexp_pack _}, {ptyp_desc = Ptyp_package _}); - } -> - Nothing - | {pexp_desc = Pexp_constraint _} -> Parenthesized - | _ -> Nothing) +let expr (expr : Parsetree.expression) = + match expr with + | {pexp_desc = Parsetree.Pexp_braces _} -> Braced expr.pexp_loc + | { + Parsetree.pexp_desc = + Pexp_constraint ({pexp_desc = Pexp_pack _}, {ptyp_desc = Ptyp_package _}); + } -> + Nothing + | {pexp_desc = Pexp_constraint _} -> Parenthesized + | _ -> Nothing let expr_record_row_rhs ~optional e = let kind = expr e in @@ -25,119 +22,107 @@ let expr_record_row_rhs ~optional e = | _ -> kind) | _ -> kind -let call_expr expr = - let opt_braces, _ = ParsetreeViewer.process_braces_attr expr in - match opt_braces with - | Some ({Location.loc = braces_loc}, _) -> Braced braces_loc - | _ -> ( - match expr with - | {Parsetree.pexp_attributes = attrs} - when match ParsetreeViewer.filter_parsing_attrs attrs with - | _ :: _ -> true - | [] -> false -> - Parenthesized - | _ - when ParsetreeViewer.is_unary_expression expr - || ParsetreeViewer.is_binary_expression expr -> - Parenthesized - | { - Parsetree.pexp_desc = - Pexp_constraint ({pexp_desc = Pexp_pack _}, {ptyp_desc = Ptyp_package _}); - } -> - Nothing - | {pexp_desc = Pexp_fun _} - when ParsetreeViewer.is_underscore_apply_sugar expr -> - Nothing - | { - pexp_desc = - ( Pexp_lazy _ | Pexp_assert _ | Pexp_fun _ | Pexp_newtype _ - | Pexp_constraint _ | Pexp_setfield _ | Pexp_match _ | Pexp_try _ - | Pexp_while _ | Pexp_for _ | Pexp_ifthenelse _ ); - } -> - Parenthesized - | _ when Ast_uncurried.expr_is_uncurried_fun expr -> Parenthesized - | _ when ParsetreeViewer.has_await_attribute expr.pexp_attributes -> - Parenthesized - | _ -> Nothing) +let call_expr (expr : Parsetree.expression) = + match expr with + | {pexp_desc = Pexp_braces _} -> Braced expr.pexp_loc + | {Parsetree.pexp_attributes = attrs} + when match ParsetreeViewer.filter_parsing_attrs attrs with + | _ :: _ -> true + | [] -> false -> + Parenthesized + | _ + when ParsetreeViewer.is_unary_expression expr + || ParsetreeViewer.is_binary_expression expr -> + Parenthesized + | { + Parsetree.pexp_desc = + Pexp_constraint ({pexp_desc = Pexp_pack _}, {ptyp_desc = Ptyp_package _}); + } -> + Nothing + | {pexp_desc = Pexp_fun _} when ParsetreeViewer.is_underscore_apply_sugar expr + -> + Nothing + | { + pexp_desc = + ( Pexp_lazy _ | Pexp_assert _ | Pexp_fun _ | Pexp_newtype _ + | Pexp_constraint _ | Pexp_setfield _ | Pexp_match _ | Pexp_try _ + | Pexp_while _ | Pexp_for _ | Pexp_ifthenelse _ ); + } -> + Parenthesized + | _ when Ast_uncurried.expr_is_uncurried_fun expr -> Parenthesized + | _ when ParsetreeViewer.has_await_attribute expr.pexp_attributes -> + Parenthesized + | _ -> Nothing -let structure_expr expr = - let opt_braces, _ = ParsetreeViewer.process_braces_attr expr in - match opt_braces with - | Some ({Location.loc = braces_loc}, _) -> Braced braces_loc - | None -> ( - match expr with - | _ - when ParsetreeViewer.has_attributes expr.pexp_attributes - && not (ParsetreeViewer.is_jsx_expression expr) -> - Parenthesized - | { - Parsetree.pexp_desc = - Pexp_constraint ({pexp_desc = Pexp_pack _}, {ptyp_desc = Ptyp_package _}); - } -> - Nothing - | {pexp_desc = Pexp_constraint _} -> Parenthesized - | _ -> Nothing) +let structure_expr (expr : Parsetree.expression) = + match expr with + | {pexp_desc = Pexp_braces _} -> Braced expr.pexp_loc + | _ + when ParsetreeViewer.has_attributes expr.pexp_attributes + && not (ParsetreeViewer.is_jsx_expression expr) -> + Parenthesized + | { + Parsetree.pexp_desc = + Pexp_constraint ({pexp_desc = Pexp_pack _}, {ptyp_desc = Ptyp_package _}); + } -> + Nothing + | {pexp_desc = Pexp_constraint _} -> Parenthesized + | _ -> Nothing -let unary_expr_operand expr = - let opt_braces, _ = ParsetreeViewer.process_braces_attr expr in - match opt_braces with - | Some ({Location.loc = braces_loc}, _) -> Braced braces_loc - | None -> ( - match expr with - | {Parsetree.pexp_attributes = attrs} - when match ParsetreeViewer.filter_parsing_attrs attrs with - | _ :: _ -> true - | [] -> false -> - Parenthesized - | expr - when ParsetreeViewer.is_unary_expression expr - || ParsetreeViewer.is_binary_expression expr -> - Parenthesized - | { - pexp_desc = - Pexp_constraint ({pexp_desc = Pexp_pack _}, {ptyp_desc = Ptyp_package _}); - } -> - Nothing - | {pexp_desc = Pexp_fun _} - when ParsetreeViewer.is_underscore_apply_sugar expr -> - Nothing - | { - pexp_desc = - ( Pexp_lazy _ | Pexp_assert _ | Pexp_fun _ | Pexp_newtype _ - | Pexp_constraint _ | Pexp_setfield _ - | Pexp_extension _ (* readability? maybe remove *) | Pexp_match _ - | Pexp_try _ | Pexp_while _ | Pexp_for _ | Pexp_ifthenelse _ ); - } -> - Parenthesized - | _ when ParsetreeViewer.has_await_attribute expr.pexp_attributes -> - Parenthesized - | _ -> Nothing) +let unary_expr_operand (expr : Parsetree.expression) = + match expr with + | {pexp_desc = Pexp_braces _} -> Braced expr.pexp_loc + | {Parsetree.pexp_attributes = attrs} + when match ParsetreeViewer.filter_parsing_attrs attrs with + | _ :: _ -> true + | [] -> false -> + Parenthesized + | expr + when ParsetreeViewer.is_unary_expression expr + || ParsetreeViewer.is_binary_expression expr -> + Parenthesized + | { + pexp_desc = + Pexp_constraint ({pexp_desc = Pexp_pack _}, {ptyp_desc = Ptyp_package _}); + } -> + Nothing + | {pexp_desc = Pexp_fun _} when ParsetreeViewer.is_underscore_apply_sugar expr + -> + Nothing + | { + pexp_desc = + ( Pexp_lazy _ | Pexp_assert _ | Pexp_fun _ | Pexp_newtype _ + | Pexp_constraint _ | Pexp_setfield _ + | Pexp_extension _ (* readability? maybe remove *) | Pexp_match _ + | Pexp_try _ | Pexp_while _ | Pexp_for _ | Pexp_ifthenelse _ ); + } -> + Parenthesized + | _ when ParsetreeViewer.has_await_attribute expr.pexp_attributes -> + Parenthesized + | _ -> Nothing -let binary_expr_operand ~is_lhs expr = - let opt_braces, _ = ParsetreeViewer.process_braces_attr expr in - match opt_braces with - | Some ({Location.loc = braces_loc}, _) -> Braced braces_loc - | None -> ( - match expr with - | { - Parsetree.pexp_desc = - Pexp_constraint ({pexp_desc = Pexp_pack _}, {ptyp_desc = Ptyp_package _}); - } -> - Nothing - | {pexp_desc = Pexp_fun _} - when ParsetreeViewer.is_underscore_apply_sugar expr -> - Nothing - | {pexp_desc = Pexp_constraint _ | Pexp_fun _ | Pexp_newtype _} -> - Parenthesized - | _ when Ast_uncurried.expr_is_uncurried_fun expr -> Parenthesized - | expr when ParsetreeViewer.is_binary_expression expr -> Parenthesized - | expr when ParsetreeViewer.is_ternary_expr expr -> Parenthesized - | {pexp_desc = Pexp_lazy _ | Pexp_assert _} when is_lhs -> Parenthesized - | _ when ParsetreeViewer.has_await_attribute expr.pexp_attributes -> - Parenthesized - | {Parsetree.pexp_attributes = attrs} -> - if ParsetreeViewer.has_printable_attributes attrs then Parenthesized - else Nothing) +let binary_expr_operand ~is_lhs (expr : Parsetree.expression) = + match expr with + | {pexp_desc = Pexp_braces _} -> Braced expr.pexp_loc + | { + Parsetree.pexp_desc = + Pexp_constraint ({pexp_desc = Pexp_pack _}, {ptyp_desc = Ptyp_package _}); + } -> + Nothing + | {pexp_desc = Pexp_fun _} when ParsetreeViewer.is_underscore_apply_sugar expr + -> + Nothing + | {pexp_desc = Pexp_constraint _ | Pexp_fun _ | Pexp_newtype _} -> + Parenthesized + | _ when Ast_uncurried.expr_is_uncurried_fun expr -> Parenthesized + | expr when ParsetreeViewer.is_binary_expression expr -> Parenthesized + | expr when ParsetreeViewer.is_ternary_expr expr -> Parenthesized + | {pexp_desc = Pexp_lazy _ | Pexp_assert _} when is_lhs -> Parenthesized + | _ when ParsetreeViewer.has_await_attribute expr.pexp_attributes -> + Parenthesized + | {Parsetree.pexp_attributes = attrs} -> + if ParsetreeViewer.has_printable_attributes attrs then Parenthesized + else Nothing let sub_binary_expr_operand parent_operator child_operator = let open ParsetreeViewer in @@ -193,46 +178,44 @@ let binary_operator_inside_await_needs_parens operator = ParsetreeViewer.operator_precedence operator < ParsetreeViewer.operator_precedence "->" -let lazy_or_assert_or_await_expr_rhs ?(in_await = false) expr = - let opt_braces, _ = ParsetreeViewer.process_braces_attr expr in - match opt_braces with - | Some ({Location.loc = braces_loc}, _) -> Braced braces_loc - | None -> ( - match expr with - | {Parsetree.pexp_attributes = attrs} - when match ParsetreeViewer.filter_parsing_attrs attrs with - | _ :: _ -> true - | [] -> false -> - Parenthesized - | { - pexp_desc = - Pexp_apply - {funct = {pexp_desc = Pexp_ident {txt = Longident.Lident operator}}}; - } - when ParsetreeViewer.is_binary_expression expr -> - if in_await && not (binary_operator_inside_await_needs_parens operator) - then Nothing - else Parenthesized - | { - pexp_desc = - Pexp_constraint ({pexp_desc = Pexp_pack _}, {ptyp_desc = Ptyp_package _}); - } -> - Nothing - | {pexp_desc = Pexp_fun _} - when ParsetreeViewer.is_underscore_apply_sugar expr -> +let lazy_or_assert_or_await_expr_rhs ?(in_await = false) + (expr : Parsetree.expression) = + match expr with + | {pexp_desc = Pexp_braces _} -> Braced expr.pexp_loc + | {Parsetree.pexp_attributes = attrs} + when match ParsetreeViewer.filter_parsing_attrs attrs with + | _ :: _ -> true + | [] -> false -> + Parenthesized + | { + pexp_desc = + Pexp_apply + {funct = {pexp_desc = Pexp_ident {txt = Longident.Lident operator}}}; + } + when ParsetreeViewer.is_binary_expression expr -> + if in_await && not (binary_operator_inside_await_needs_parens operator) then Nothing - | { - pexp_desc = - ( Pexp_lazy _ | Pexp_assert _ | Pexp_fun _ | Pexp_newtype _ - | Pexp_constraint _ | Pexp_setfield _ | Pexp_match _ | Pexp_try _ - | Pexp_while _ | Pexp_for _ | Pexp_ifthenelse _ ); - } -> - Parenthesized - | _ - when (not in_await) - && ParsetreeViewer.has_await_attribute expr.pexp_attributes -> - Parenthesized - | _ -> Nothing) + else Parenthesized + | { + pexp_desc = + Pexp_constraint ({pexp_desc = Pexp_pack _}, {ptyp_desc = Ptyp_package _}); + } -> + Nothing + | {pexp_desc = Pexp_fun _} when ParsetreeViewer.is_underscore_apply_sugar expr + -> + Nothing + | { + pexp_desc = + ( Pexp_lazy _ | Pexp_assert _ | Pexp_fun _ | Pexp_newtype _ + | Pexp_constraint _ | Pexp_setfield _ | Pexp_match _ | Pexp_try _ + | Pexp_while _ | Pexp_for _ | Pexp_ifthenelse _ ); + } -> + Parenthesized + | _ + when (not in_await) + && ParsetreeViewer.has_await_attribute expr.pexp_attributes -> + Parenthesized + | _ -> Nothing let is_negative_constant constant = let is_neg txt = @@ -244,74 +227,65 @@ let is_negative_constant constant = true | _ -> false -let field_expr expr = - let opt_braces, _ = ParsetreeViewer.process_braces_attr expr in - match opt_braces with - | Some ({Location.loc = braces_loc}, _) -> Braced braces_loc - | None -> ( - match expr with - | {Parsetree.pexp_attributes = attrs} - when match ParsetreeViewer.filter_parsing_attrs attrs with - | _ :: _ -> true - | [] -> false -> - Parenthesized - | expr - when ParsetreeViewer.is_binary_expression expr - || ParsetreeViewer.is_unary_expression expr -> - Parenthesized - | { - pexp_desc = - Pexp_constraint ({pexp_desc = Pexp_pack _}, {ptyp_desc = Ptyp_package _}); - } -> - Nothing - | {pexp_desc = Pexp_constant c} when is_negative_constant c -> Parenthesized - | {pexp_desc = Pexp_fun _} - when ParsetreeViewer.is_underscore_apply_sugar expr -> - Nothing - | { - pexp_desc = - ( Pexp_lazy _ | Pexp_assert _ - | Pexp_extension _ (* %extension.x vs (%extension).x *) | Pexp_fun _ - | Pexp_newtype _ | Pexp_constraint _ | Pexp_setfield _ | Pexp_match _ - | Pexp_try _ | Pexp_while _ | Pexp_for _ | Pexp_ifthenelse _ ); - } -> - Parenthesized - | _ when ParsetreeViewer.has_await_attribute expr.pexp_attributes -> - Parenthesized - | _ -> Nothing) +let field_expr (expr : Parsetree.expression) = + match expr with + | {pexp_desc = Pexp_braces _} -> Braced expr.pexp_loc + | {Parsetree.pexp_attributes = attrs} + when match ParsetreeViewer.filter_parsing_attrs attrs with + | _ :: _ -> true + | [] -> false -> + Parenthesized + | expr + when ParsetreeViewer.is_binary_expression expr + || ParsetreeViewer.is_unary_expression expr -> + Parenthesized + | { + pexp_desc = + Pexp_constraint ({pexp_desc = Pexp_pack _}, {ptyp_desc = Ptyp_package _}); + } -> + Nothing + | {pexp_desc = Pexp_constant c} when is_negative_constant c -> Parenthesized + | {pexp_desc = Pexp_fun _} when ParsetreeViewer.is_underscore_apply_sugar expr + -> + Nothing + | { + pexp_desc = + ( Pexp_lazy _ | Pexp_assert _ + | Pexp_extension _ (* %extension.x vs (%extension).x *) | Pexp_fun _ + | Pexp_newtype _ | Pexp_constraint _ | Pexp_setfield _ | Pexp_match _ + | Pexp_try _ | Pexp_while _ | Pexp_for _ | Pexp_ifthenelse _ ); + } -> + Parenthesized + | _ when ParsetreeViewer.has_await_attribute expr.pexp_attributes -> + Parenthesized + | _ -> Nothing -let set_field_expr_rhs expr = - let opt_braces, _ = ParsetreeViewer.process_braces_attr expr in - match opt_braces with - | Some ({Location.loc = braces_loc}, _) -> Braced braces_loc - | None -> ( - match expr with - | { - Parsetree.pexp_desc = - Pexp_constraint ({pexp_desc = Pexp_pack _}, {ptyp_desc = Ptyp_package _}); - } -> - Nothing - | {pexp_desc = Pexp_constraint _} -> Parenthesized - | _ -> Nothing) +let set_field_expr_rhs (expr : Parsetree.expression) = + match expr with + | {pexp_desc = Pexp_braces _} -> Braced expr.pexp_loc + | { + Parsetree.pexp_desc = + Pexp_constraint ({pexp_desc = Pexp_pack _}, {ptyp_desc = Ptyp_package _}); + } -> + Nothing + | {pexp_desc = Pexp_constraint _} -> Parenthesized + | _ -> Nothing -let ternary_operand expr = - let opt_braces, _ = ParsetreeViewer.process_braces_attr expr in - match opt_braces with - | Some ({Location.loc = braces_loc}, _) -> Braced braces_loc - | None -> ( - match expr with - | { - Parsetree.pexp_desc = - Pexp_constraint ({pexp_desc = Pexp_pack _}, {ptyp_desc = Ptyp_package _}); - } -> - Nothing - | {pexp_desc = Pexp_constraint _} -> Parenthesized - | _ when Res_parsetree_viewer.is_fun_newtype expr -> ( - let _, _parameters, return_expr = ParsetreeViewer.fun_expr expr in - match return_expr.pexp_desc with - | Pexp_constraint _ -> Parenthesized - | _ -> Nothing) +let ternary_operand (expr : Parsetree.expression) = + match expr with + | {pexp_desc = Pexp_braces _} -> Braced expr.pexp_loc + | { + Parsetree.pexp_desc = + Pexp_constraint ({pexp_desc = Pexp_pack _}, {ptyp_desc = Ptyp_package _}); + } -> + Nothing + | {pexp_desc = Pexp_constraint _} -> Parenthesized + | _ when Res_parsetree_viewer.is_fun_newtype expr -> ( + let _, _parameters, return_expr = ParsetreeViewer.fun_expr expr in + match return_expr.pexp_desc with + | Pexp_constraint _ -> Parenthesized | _ -> Nothing) + | _ -> Nothing let starts_with_minus txt = let len = String.length txt in @@ -326,37 +300,33 @@ let jsx_prop_expr expr = | Pexp_letmodule _ | Pexp_open _ -> Nothing | _ -> ( - let opt_braces, _ = ParsetreeViewer.process_braces_attr expr in - match opt_braces with - | Some ({Location.loc = braces_loc}, _) -> Braced braces_loc - | None -> ( - match expr with - | { - Parsetree.pexp_desc = - Pexp_constant (Pconst_integer (x, _) | Pconst_float (x, _)); - pexp_attributes = []; - } - when starts_with_minus x -> - Parenthesized - | _ when ParsetreeViewer.has_await_attribute expr.pexp_attributes -> - Parenthesized - | { - Parsetree.pexp_desc = - ( Pexp_ident _ | Pexp_constant _ | Pexp_field _ | Pexp_construct _ - | Pexp_variant _ | Pexp_array _ | Pexp_pack _ | Pexp_record _ - | Pexp_extension _ | Pexp_letmodule _ | Pexp_letexception _ - | Pexp_open _ | Pexp_sequence _ | Pexp_let _ | Pexp_tuple _ ); - pexp_attributes = []; - } -> - Nothing - | { - Parsetree.pexp_desc = - Pexp_constraint - ({pexp_desc = Pexp_pack _}, {ptyp_desc = Ptyp_package _}); - pexp_attributes = []; - } -> - Nothing - | _ -> Parenthesized)) + match expr with + | {pexp_desc = Pexp_braces _} -> Braced expr.pexp_loc + | { + Parsetree.pexp_desc = + Pexp_constant (Pconst_integer (x, _) | Pconst_float (x, _)); + pexp_attributes = []; + } + when starts_with_minus x -> + Parenthesized + | _ when ParsetreeViewer.has_await_attribute expr.pexp_attributes -> + Parenthesized + | { + Parsetree.pexp_desc = + ( Pexp_ident _ | Pexp_constant _ | Pexp_field _ | Pexp_construct _ + | Pexp_variant _ | Pexp_array _ | Pexp_pack _ | Pexp_record _ + | Pexp_extension _ | Pexp_letmodule _ | Pexp_letexception _ | Pexp_open _ + | Pexp_sequence _ | Pexp_let _ | Pexp_tuple _ ); + pexp_attributes = []; + } -> + Nothing + | { + Parsetree.pexp_desc = + Pexp_constraint ({pexp_desc = Pexp_pack _}, {ptyp_desc = Ptyp_package _}); + pexp_attributes = []; + } -> + Nothing + | _ -> Parenthesized) let jsx_child_expr expr = match expr.Parsetree.pexp_desc with @@ -364,49 +334,42 @@ let jsx_child_expr expr = | Pexp_letmodule _ | Pexp_open _ -> Nothing | _ -> ( - let opt_braces, _ = ParsetreeViewer.process_braces_attr expr in - match opt_braces with - | Some ({Location.loc = braces_loc}, _) -> Braced braces_loc - | _ -> ( - match expr with - | { - Parsetree.pexp_desc = - Pexp_constant (Pconst_integer (x, _) | Pconst_float (x, _)); - pexp_attributes = []; - } - when starts_with_minus x -> - Parenthesized - | _ when ParsetreeViewer.has_await_attribute expr.pexp_attributes -> - Parenthesized - | { - Parsetree.pexp_desc = - ( Pexp_ident _ | Pexp_constant _ | Pexp_field _ | Pexp_construct _ - | Pexp_variant _ | Pexp_array _ | Pexp_pack _ | Pexp_record _ - | Pexp_extension _ | Pexp_letmodule _ | Pexp_letexception _ - | Pexp_open _ | Pexp_sequence _ | Pexp_let _ ); - pexp_attributes = []; - } -> - Nothing - | { - Parsetree.pexp_desc = - Pexp_constraint - ({pexp_desc = Pexp_pack _}, {ptyp_desc = Ptyp_package _}); - pexp_attributes = []; - } -> - Nothing - | expr when ParsetreeViewer.is_jsx_expression expr -> Nothing - | _ -> Parenthesized)) - -let binary_expr expr = - let opt_braces, _ = ParsetreeViewer.process_braces_attr expr in - match opt_braces with - | Some ({Location.loc = braces_loc}, _) -> Braced braces_loc - | None -> ( match expr with - | {Parsetree.pexp_attributes = _ :: _} as expr - when ParsetreeViewer.is_binary_expression expr -> + | {pexp_desc = Pexp_braces _} -> Braced expr.pexp_loc + | { + Parsetree.pexp_desc = + Pexp_constant (Pconst_integer (x, _) | Pconst_float (x, _)); + pexp_attributes = []; + } + when starts_with_minus x -> Parenthesized - | _ -> Nothing) + | _ when ParsetreeViewer.has_await_attribute expr.pexp_attributes -> + Parenthesized + | { + Parsetree.pexp_desc = + ( Pexp_ident _ | Pexp_constant _ | Pexp_field _ | Pexp_construct _ + | Pexp_variant _ | Pexp_array _ | Pexp_pack _ | Pexp_record _ + | Pexp_extension _ | Pexp_letmodule _ | Pexp_letexception _ | Pexp_open _ + | Pexp_sequence _ | Pexp_let _ ); + pexp_attributes = []; + } -> + Nothing + | { + Parsetree.pexp_desc = + Pexp_constraint ({pexp_desc = Pexp_pack _}, {ptyp_desc = Ptyp_package _}); + pexp_attributes = []; + } -> + Nothing + | expr when ParsetreeViewer.is_jsx_expression expr -> Nothing + | _ -> Parenthesized) + +let binary_expr (expr : Parsetree.expression) = + match expr with + | {pexp_desc = Pexp_braces _} -> Braced expr.pexp_loc + | {Parsetree.pexp_attributes = _ :: _} as expr + when ParsetreeViewer.is_binary_expression expr -> + Parenthesized + | _ -> Nothing let mod_type_functor_return mod_type = match mod_type with diff --git a/compiler/syntax/src/res_parsetree_viewer.ml b/compiler/syntax/src/res_parsetree_viewer.ml index 3544e9e3fc..bdf5faf9b0 100644 --- a/compiler/syntax/src/res_parsetree_viewer.ml +++ b/compiler/syntax/src/res_parsetree_viewer.ml @@ -191,22 +191,15 @@ let fun_expr expr_ = collect_params ~n_fun:0 ~params:[param] return_expr | _ -> collect_params ~n_fun:0 ~params:[] {expr_ with pexp_attributes = []} -let process_braces_attr expr = - match expr.pexp_attributes with - | (({txt = "res.braces" | "ns.braces"}, _) as attr) :: attrs -> - (Some attr, {expr with pexp_attributes = attrs}) - | _ -> (None, expr) - let filter_parsing_attrs attrs = List.filter (fun attr -> match attr with | ( { Location.txt = - ( "res.braces" | "ns.braces" | "res.iflet" | "res.ternary" - | "res.await" | "res.template" | "res.taggedTemplate" - | "res.patVariantSpread" | "res.dictPattern" - | "res.inlineRecordDefinition" ); + ( "res.iflet" | "res.ternary" | "res.await" | "res.template" + | "res.taggedTemplate" | "res.patVariantSpread" + | "res.dictPattern" | "res.inlineRecordDefinition" ); }, _ ) -> false @@ -221,8 +214,8 @@ let is_block_expr expr = | _ -> false let is_braced_expr expr = - match process_braces_attr expr with - | Some _, _ -> true + match expr.pexp_desc with + | Pexp_braces _ -> true | _ -> false let is_multiline_text txt = @@ -360,8 +353,8 @@ let has_attributes attrs = match attr with | ( { Location.txt = - ( "res.braces" | "ns.braces" | "res.iflet" | "res.ternary" - | "res.await" | "res.template" | "res.inlineRecordDefinition" ); + ( "res.iflet" | "res.ternary" | "res.await" | "res.template" + | "res.inlineRecordDefinition" ); }, _ ) -> false @@ -555,8 +548,8 @@ let is_printable_attribute attr = match attr with | ( { Location.txt = - ( "res.iflet" | "res.braces" | "ns.braces" | "JSX" | "res.await" - | "res.template" | "res.ternary" | "res.inlineRecordDefinition" ); + ( "ns.braces" | "JSX" | "res.await" | "res.template" | "res.ternary" + | "res.inlineRecordDefinition" ); }, _ ) -> false diff --git a/compiler/syntax/src/res_parsetree_viewer.mli b/compiler/syntax/src/res_parsetree_viewer.mli index a027c78911..9d18fa6f5a 100644 --- a/compiler/syntax/src/res_parsetree_viewer.mli +++ b/compiler/syntax/src/res_parsetree_viewer.mli @@ -136,9 +136,6 @@ val is_spread_belt_array_concat : Parsetree.expression -> bool val collect_or_pattern_chain : Parsetree.pattern -> Parsetree.pattern list -val process_braces_attr : - Parsetree.expression -> Parsetree.attribute option * Parsetree.expression - val filter_parsing_attrs : Parsetree.attributes -> Parsetree.attributes val is_braced_expr : Parsetree.expression -> bool diff --git a/compiler/syntax/src/res_printer.ml b/compiler/syntax/src/res_printer.ml index 3b88fe5f43..77b9febfcf 100644 --- a/compiler/syntax/src/res_printer.ml +++ b/compiler/syntax/src/res_printer.ml @@ -2085,7 +2085,11 @@ and print_value_binding ~state ~rec_flag (vb : Parsetree.value_binding) cmt_tbl ]); ])) | _ -> - let opt_braces, expr = ParsetreeViewer.process_braces_attr vb.pvb_expr in + let opt_braces, expr = + match vb.pvb_expr.pexp_desc with + | Parsetree.Pexp_braces inner -> (Some vb.pvb_expr.pexp_loc, inner) + | _ -> (None, vb.pvb_expr) + in let printed_expr = let doc = print_expression_with_comments ~state vb.pvb_expr cmt_tbl in match Parens.expr vb.pvb_expr with @@ -2689,9 +2693,9 @@ and print_if_chain ~state pexp_attributes ifs else_expr cmt_tbl = Doc.group condition; Doc.space; (let then_expr = - match ParsetreeViewer.process_braces_attr then_expr with + match then_expr.Parsetree.pexp_desc with (* This case only happens when coming from Reason, we strip braces *) - | Some _, expr -> expr + | Pexp_braces inner -> inner | _ -> then_expr in print_expression_block ~state ~braces:true then_expr cmt_tbl); @@ -2758,14 +2762,11 @@ and print_expression ~state (e : Parsetree.expression) cmt_tbl = ~has_constraint parameters cmt_tbl in let return_expr_doc = - let opt_braces, _ = ParsetreeViewer.process_braces_attr return_expr in let should_inline = - match (return_expr.pexp_desc, opt_braces) with - | _, Some _ -> true - | ( ( Pexp_array _ | Pexp_tuple _ - | Pexp_construct (_, Some _) - | Pexp_record _ ), - _ ) -> + match return_expr.Parsetree.pexp_desc with + | Pexp_braces _ | Pexp_array _ | Pexp_tuple _ + | Pexp_construct (_, Some _) + | Pexp_record _ -> true | _ -> false in @@ -2816,6 +2817,13 @@ and print_expression ~state (e : Parsetree.expression) cmt_tbl = in let printed_expression = match e_fun.pexp_desc with + | Pexp_braces inner -> + Doc.concat + [ + Doc.lbrace; + print_expression_with_comments ~state inner cmt_tbl; + Doc.rbrace; + ] | Pexp_fun { arg_label = Nolabel; @@ -3436,18 +3444,7 @@ and print_expression ~state (e : Parsetree.expression) cmt_tbl = let expr_with_await = if ParsetreeViewer.has_await_attribute e.pexp_attributes then let rhs = - match - Parens.lazy_or_assert_or_await_expr_rhs ~in_await:true - { - e with - pexp_attributes = - List.filter - (function - | {Location.txt = "res.braces" | "ns.braces"}, _ -> false - | _ -> true) - e.pexp_attributes; - } - with + match Parens.lazy_or_assert_or_await_expr_rhs ~in_await:true e with | Parens.Parenthesized -> add_parens printed_expression | Braced braces -> print_braces printed_expression e braces | Nothing -> printed_expression @@ -3503,14 +3500,11 @@ and print_pexp_fun ~state ~in_callback e cmt_tbl = | _ -> true in let return_expr_doc = - let opt_braces, _ = ParsetreeViewer.process_braces_attr return_expr in let should_inline = - match (return_expr.pexp_desc, opt_braces) with - | _, Some _ -> true - | ( ( Pexp_array _ | Pexp_tuple _ - | Pexp_construct (_, Some _) - | Pexp_record _ ), - _ ) -> + match return_expr.pexp_desc with + | Parsetree.Pexp_braces _ -> true + | Pexp_array _ | Pexp_tuple _ | Pexp_construct (_, Some _) | Pexp_record _ + -> true | _ -> false in @@ -4501,11 +4495,7 @@ and print_jsx_children ~state (children_expr : Parsetree.expression) ~sep | None -> loc | Some comment -> Comment.loc comment in - let get_loc expr = - match ParsetreeViewer.process_braces_attr expr with - | None, _ -> get_first_leading_comment expr.pexp_loc - | Some ({loc}, _), _ -> get_first_leading_comment loc - in + let get_loc expr = get_first_leading_comment expr.Parsetree.pexp_loc in let rec loop prev acc exprs = match exprs with | [] -> List.rev acc @@ -5033,10 +5023,7 @@ and print_cases ~state (cases : Parsetree.case list) cmt_tbl = ~get_loc:(fun n -> { n.Parsetree.pc_lhs.ppat_loc with - loc_end = - (match ParsetreeViewer.process_braces_attr n.pc_rhs with - | None, _ -> n.pc_rhs.pexp_loc.loc_end - | Some ({loc}, _), _ -> loc.Location.loc_end); + loc_end = n.pc_rhs.pexp_loc.loc_end; }) ~print:(print_case ~state) ~nodes:cases cmt_tbl; ]; From 2b3ae11a7e77d449539ea999fdd95b1a89868b61 Mon Sep 17 00:00:00 2001 From: nojaf Date: Tue, 1 Apr 2025 09:05:35 +0200 Subject: [PATCH 2/2] Slightly better printer results, but still rather meh --- compiler/syntax/src/res_comments_table.ml | 1 + compiler/syntax/src/res_printer.ml | 45 +++++++++++++---------- 2 files changed, 27 insertions(+), 19 deletions(-) diff --git a/compiler/syntax/src/res_comments_table.ml b/compiler/syntax/src/res_comments_table.ml index b3e080b20f..115a3119e3 100644 --- a/compiler/syntax/src/res_comments_table.ml +++ b/compiler/syntax/src/res_comments_table.ml @@ -1499,6 +1499,7 @@ and walk_expression expr t comments = attach t.leading return_expr.pexp_loc leading; walk_expression return_expr t inside; attach t.trailing return_expr.pexp_loc trailing) + | Pexp_braces inner -> walk_list [Expression inner] t comments | _ -> () and walk_expr_parameter (_attrs, _argLbl, expr_opt, pattern) t comments = diff --git a/compiler/syntax/src/res_printer.ml b/compiler/syntax/src/res_printer.ml index 77b9febfcf..60e2d0e9ad 100644 --- a/compiler/syntax/src/res_printer.ml +++ b/compiler/syntax/src/res_printer.ml @@ -26,6 +26,11 @@ let add_parens doc = Doc.rparen; ]) +let unwrap_braces expr = + match expr.Parsetree.pexp_desc with + | Pexp_braces inner -> inner + | _ -> expr + let add_braces doc = Doc.group (Doc.concat @@ -606,7 +611,9 @@ and print_structure_item ~state (si : Parsetree.structure_item) cmt_tbl = print_value_description ~state value_description cmt_tbl | Pstr_eval (expr, attrs) -> let expr_doc = - let doc = print_expression_with_comments ~state expr cmt_tbl in + let doc = + print_expression_with_comments ~state (unwrap_braces expr) cmt_tbl + in match Parens.structure_expr expr with | Parens.Parenthesized -> add_parens doc | Braced braces -> print_braces doc expr braces @@ -2085,16 +2092,20 @@ and print_value_binding ~state ~rec_flag (vb : Parsetree.value_binding) cmt_tbl ]); ])) | _ -> - let opt_braces, expr = + let has_braces = match vb.pvb_expr.pexp_desc with - | Parsetree.Pexp_braces inner -> (Some vb.pvb_expr.pexp_loc, inner) - | _ -> (None, vb.pvb_expr) + | Parsetree.Pexp_braces _ -> true + | _ -> false in let printed_expr = - let doc = print_expression_with_comments ~state vb.pvb_expr cmt_tbl in + let doc = + print_expression_with_comments ~state + (unwrap_braces vb.pvb_expr) + cmt_tbl + in match Parens.expr vb.pvb_expr with | Parens.Parenthesized -> add_parens doc - | Braced braces -> print_braces doc expr braces + | Braced braces -> print_braces doc vb.pvb_expr braces | Nothing -> doc in let pattern_doc = print_pattern ~state vb.pvb_pat cmt_tbl in @@ -2135,10 +2146,9 @@ and print_value_binding ~state ~rec_flag (vb : Parsetree.value_binding) cmt_tbl ] else let should_indent = - match opt_braces with - | Some _ -> false - | _ -> ( - ParsetreeViewer.is_binary_expression expr + if has_braces then false + else + ParsetreeViewer.is_binary_expression vb.pvb_expr || match vb.pvb_expr with | { @@ -2152,7 +2162,7 @@ and print_value_binding ~state ~rec_flag (vb : Parsetree.value_binding) cmt_tbl false | e -> ParsetreeViewer.has_attributes e.pexp_attributes - || ParsetreeViewer.is_array_access e) + || ParsetreeViewer.is_array_access e in Doc.group (Doc.concat @@ -2664,7 +2674,7 @@ and print_pattern_dict_row ~state and print_expression_with_comments ~state expr cmt_tbl : Doc.t = let doc = print_expression ~state expr cmt_tbl in - print_comments doc cmt_tbl expr.Parsetree.pexp_loc + print_comments doc cmt_tbl (unwrap_braces expr).Parsetree.pexp_loc and print_if_chain ~state pexp_attributes ifs else_expr cmt_tbl = let if_docs = @@ -2818,12 +2828,8 @@ and print_expression ~state (e : Parsetree.expression) cmt_tbl = let printed_expression = match e_fun.pexp_desc with | Pexp_braces inner -> - Doc.concat - [ - Doc.lbrace; - print_expression_with_comments ~state inner cmt_tbl; - Doc.rbrace; - ] + (* the rules for printing braces are all over the place *) + print_expression ~state inner cmt_tbl | Pexp_fun { arg_label = Nolabel; @@ -5418,7 +5424,8 @@ and print_expression_block ~state ~braces expr cmt_tbl = * a + b * } *) -and print_braces doc expr braces_loc = +and print_braces doc (expr : Parsetree.expression) (braces_loc : Warnings.loc) = + let expr = unwrap_braces expr in let over_multiple_lines = let open Location in braces_loc.loc_end.pos_lnum > braces_loc.loc_start.pos_lnum