diff --git a/CHANGES.md b/CHANGES.md index 9991716aa6..d454091d21 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -33,6 +33,7 @@ profile. This started with version 0.26.0. - Fix unstable comment around docked functor argument (#2506, @Julow) - \* Fix unwanted alignment after comment (#2507, @Julow) - \* Fix unwanted alignment in if-then-else (#2511, @Julow) +- Fix position of comments around and within `(type ...)` function arguments (#2503, @gpetiot) ## 0.26.1 (2023-09-15) diff --git a/lib/Ast.ml b/lib/Ast.ml index 0a45f0a00a..522342075d 100644 --- a/lib/Ast.ml +++ b/lib/Ast.ml @@ -640,7 +640,8 @@ module T = struct | Ctd of class_type_declaration | Pat of pattern | Exp of expression - | Fp of function_param + | Fpe of expr_function_param + | Fpc of class_function_param | Vc of value_constraint | Lb of value_binding | Bo of binding_op @@ -663,7 +664,8 @@ module T = struct | Td t -> Format.fprintf fs "Td:@\n%a" Printast.type_declaration t | Pat p -> Format.fprintf fs "Pat:@\n%a" Printast.pattern p | Exp e -> Format.fprintf fs "Exp:@\n%a" Printast.expression e - | Fp p -> Format.fprintf fs "Fp:@\n%a" Printast.function_param p + | Fpe p -> Format.fprintf fs "Fpe:@\n%a" Printast.expr_function_param p + | Fpc p -> Format.fprintf fs "Fpc:@\n%a" Printast.class_function_param p | Vc c -> Format.fprintf fs "Vc:@\n%a" Printast.value_constraint c | Lb b -> Format.fprintf fs "Lb:@\n%a" Printast.value_binding b | Bo b -> Format.fprintf fs "Bo:@\n%a" Printast.binding_op b @@ -701,7 +703,7 @@ let attributes = function | Cty x -> x.pcty_attributes | Pat x -> x.ppat_attributes | Exp x -> x.pexp_attributes - | Fp _ -> [] + | Fpe _ | Fpc _ -> [] | Vc _ -> [] | Lb x -> x.pvb_attributes | Bo _ -> [] @@ -727,7 +729,8 @@ let location = function | Cty x -> x.pcty_loc | Pat x -> x.ppat_loc | Exp x -> x.pexp_loc - | Fp x -> x.pparam_loc + | Fpe x -> x.pparam_loc + | Fpc x -> x.pparam_loc | Vc _ -> Location.none | Lb x -> x.pvb_loc | Bo x -> x.pbop_loc @@ -1014,7 +1017,7 @@ end = struct | Pcoerce (t1, t2) -> Option.exists t1 ~f || f t2 ) ) ) | Pexp_let (lbs, _) -> assert (check_let_bindings lbs) | _ -> assert false ) - | Fp _ -> assert false + | Fpe _ | Fpc _ -> assert false | Vc c -> assert (check_value_constraint c) | Lb _ -> assert false | Bo _ -> assert false @@ -1106,7 +1109,7 @@ end = struct let check_cty {ctx; ast= cty} = match (ctx : t) with | Exp _ -> assert false - | Fp _ -> assert false + | Fpe _ | Fpc _ -> assert false | Vc _ -> assert false | Lb _ -> assert false | Bo _ -> assert false @@ -1165,7 +1168,7 @@ end = struct let check_cl {ctx; ast= cl} = match (ctx : t) with | Exp _ -> assert false - | Fp _ -> assert false + | Fpe _ | Fpc _ -> assert false | Vc _ -> assert false | Lb _ -> assert false | Bo _ -> assert false @@ -1217,12 +1220,18 @@ end = struct let check_bindings l = List.exists l ~f:(fun {pvb_pat; _} -> check_subpat pvb_pat) in - let check_function_param param = + let check_param_val (_, _, p) = p == pat in + let check_expr_function_param param = match param.pparam_desc with - | Pparam_val (_, _, p) -> p == pat - | Pparam_newtype _ -> false + | Param_val x -> check_param_val x + | Param_newtype _ -> false + in + let check_class_function_param param = + check_param_val param.pparam_desc + in + let check_class_function_params = + List.exists ~f:check_class_function_param in - let check_function_params l = List.exists l ~f:check_function_param in match ctx with | Pld (PPat (p1, _)) -> assert (p1 == pat) | Pld _ -> assert false @@ -1280,8 +1289,9 @@ end = struct | {pc_lhs; _} when pc_lhs == pat -> true | _ -> false ) ) | Pexp_for (p, _, _, _, _) -> assert (p == pat) - | Pexp_fun (p, _) -> assert (check_function_param p) ) - | Fp ctx -> assert (check_function_param ctx) + | Pexp_fun (p, _) -> assert (check_expr_function_param p) ) + | Fpe ctx -> assert (check_expr_function_param ctx) + | Fpc ctx -> assert (check_class_function_param ctx) | Vc _ -> assert false | Lb x -> assert (x.pvb_pat == pat) | Bo x -> assert (x.pbop_pat == pat) @@ -1290,7 +1300,7 @@ end = struct | Cl ctx -> assert ( match ctx.pcl_desc with - | Pcl_fun (p, _) -> check_function_params p + | Pcl_fun (p, _) -> check_class_function_params p | Pcl_constr _ -> false | Pcl_structure {pcstr_self; _} -> Option.exists ~f:(fun self_ -> self_ == pat) pcstr_self @@ -1332,12 +1342,18 @@ end = struct | PStr [{pstr_desc= Pstr_eval (e, _); _}] -> e == exp | _ -> false in - let check_function_param param = + let check_param_val (_, e, _) = Option.exists e ~f:(fun x -> x == exp) in + let check_expr_function_param param = match param.pparam_desc with - | Pparam_val (_, e, _) -> Option.exists e ~f:(fun x -> x == exp) - | Pparam_newtype _ -> false + | Param_val x -> check_param_val x + | Param_newtype _ -> false + in + let check_class_function_param param = + check_param_val param.pparam_desc + in + let check_class_function_params = + List.exists ~f:check_class_function_param in - let check_function_params l = List.exists l ~f:check_function_param in match ctx with | Pld (PPat (_, Some e1)) -> assert (e1 == exp) | Pld _ -> assert false @@ -1367,7 +1383,7 @@ end = struct | {pc_rhs; _} when pc_rhs == exp -> true | _ -> false ) ) | Pexp_fun (param, body) -> - assert (check_function_param param || body == exp) + assert (check_expr_function_param param || body == exp) | Pexp_indexop_access {pia_lhs; pia_kind= Builtin idx; pia_rhs; _} -> assert ( pia_lhs == exp || idx == exp @@ -1416,7 +1432,8 @@ end = struct | Pexp_for (_, e1, e2, _, e3) -> assert (e1 == exp || e2 == exp || e3 == exp) | Pexp_override e1N -> assert (List.exists e1N ~f:snd_f) ) - | Fp ctx -> assert (check_function_param ctx) + | Fpe ctx -> assert (check_expr_function_param ctx) + | Fpc ctx -> assert (check_class_function_param ctx) | Vc _ -> assert false | Lb x -> assert (x.pvb_expr == exp) | Bo x -> assert (x.pbop_exp == exp) @@ -1439,7 +1456,7 @@ end = struct | Cl ctx -> let rec loop ctx = match ctx.pcl_desc with - | Pcl_fun (param, e) -> check_function_params param || loop e + | Pcl_fun (param, e) -> check_class_function_params param || loop e | Pcl_constr _ -> false | Pcl_structure _ -> false | Pcl_apply (_, l) -> List.exists l ~f:(fun (_, e) -> e == exp) @@ -1670,8 +1687,8 @@ end = struct ; ast= ( Pld _ | Top | Tli _ | Pat _ | Cl _ | Mty _ | Mod _ | Sig _ | Str _ | Clf _ | Ctf _ | Rep | Mb _ | Md _ ) } - |{ctx= Fp _; ast= _} - |{ctx= _; ast= Fp _} + |{ctx= Fpe _ | Fpc _; ast= _} + |{ctx= _; ast= Fpe _ | Fpc _} |{ctx= Vc _; ast= _} |{ctx= _; ast= Vc _} |{ctx= Lb _; ast= _} @@ -1763,7 +1780,7 @@ end = struct | Pexp_field _ -> Some Dot | Pexp_send _ -> Some Dot | _ -> None ) - | Fp _ -> None + | Fpe _ | Fpc _ -> None | Vc _ -> None | Lb _ -> None | Bo _ -> None @@ -1884,7 +1901,8 @@ end = struct | Ppat_cons _ -> true | Ppat_construct _ | Ppat_record _ | Ppat_variant _ -> false | _ -> true ) - | Fp {pparam_desc= Pparam_val (_, _, _); _}, Ppat_cons _ -> true + | Fpe {pparam_desc= Param_val (_, _, _); _}, Ppat_cons _ -> true + | Fpc {pparam_desc= _; _}, Ppat_cons _ -> true | Pat {ppat_desc= Ppat_construct _; _}, Ppat_cons _ -> true | _, Ppat_constraint (_, {ptyp_desc= Ptyp_poly _; _}) -> false | ( Exp {pexp_desc= Pexp_letop _; _} @@ -1945,7 +1963,7 @@ end = struct | Ppat_variant _ ) ) -> true | (Str _ | Exp _), Ppat_lazy _ -> true - | ( Fp _ + | ( (Fpe _ | Fpc _) , ( Ppat_tuple _ | Ppat_construct _ | Ppat_alias _ | Ppat_variant _ | Ppat_lazy _ | Ppat_exception _ | Ppat_or _ ) ) |( Pat {ppat_desc= Ppat_construct _ | Ppat_variant _; _} diff --git a/lib/Ast.mli b/lib/Ast.mli index 0faf28ac21..5ef908ddfc 100644 --- a/lib/Ast.mli +++ b/lib/Ast.mli @@ -112,7 +112,8 @@ type t = | Ctd of class_type_declaration | Pat of pattern | Exp of expression - | Fp of function_param + | Fpe of expr_function_param + | Fpc of class_function_param | Vc of value_constraint | Lb of value_binding | Bo of binding_op diff --git a/lib/Extended_ast.ml b/lib/Extended_ast.ml index af0ff02d9b..307543a223 100644 --- a/lib/Extended_ast.ml +++ b/lib/Extended_ast.ml @@ -183,7 +183,7 @@ module Parse = struct {p with ppat_desc= Ppat_unpack (name, Some pt)} | p -> Ast_mapper.default_mapper.pat m p in - let expr (m : Ast_mapper.mapper) = function + let rec expr (m : Ast_mapper.mapper) = function | {pexp_desc= Pexp_cons (_ :: _ :: _ :: _ as l); _} as e when match List.last_exn l with (* Empty lists are always represented as Lident [] *) @@ -233,6 +233,25 @@ module Parse = struct (module S) = (module M)] - [let _ = ((module M) : (module S))] *) {p with pexp_desc= Pexp_pack (name, Some pt)} + | { pexp_desc= + Pexp_fun + ({pparam_desc= Param_newtype types1; pparam_loc= loc1}, e1) + ; pexp_attributes= [] + ; _ } as e -> + let e = + match (expr m e1).pexp_desc with + | Pexp_fun + ({pparam_desc= Param_newtype types2; pparam_loc= loc2}, e2) + -> + { e with + pexp_desc= + Pexp_fun + ( { pparam_desc= Param_newtype (types1 @ types2) + ; pparam_loc= {loc1 with loc_end= loc2.loc_end} } + , e2 ) } + | _ -> e + in + Ast_mapper.default_mapper.expr m e | e -> Ast_mapper.default_mapper.expr m e in Ast_mapper.{default_mapper with expr; pat; binding_op} diff --git a/lib/Fmt_ast.ml b/lib/Fmt_ast.ml index 417e46959d..d39a838cfb 100644 --- a/lib/Fmt_ast.ml +++ b/lib/Fmt_ast.ml @@ -726,7 +726,7 @@ and type_constr_and_body c xbody = let exp_ctx = let pat = Ast_helper.Pat.any () in let param = - { pparam_desc= Pparam_val (Nolabel, None, pat) + { pparam_desc= Param_val (Nolabel, None, pat) ; pparam_loc= pat.ppat_loc } in Exp Ast_helper.(Exp.fun_ param exp) @@ -1258,96 +1258,100 @@ and fmt_pattern ?ext c ?pro ?parens ?(box = false) $ wrap_k (str opn) (str cls) (fmt "@;<0 2>" $ fmt_pattern c (sub_pat ~ctx pat)) ) -and fmt_fun_args c args = - let fmt_fun_arg (a : function_param) = - let ctx = Fp a in - Cmts.fmt c a.pparam_loc - @@ - match a.pparam_desc with - | Pparam_val - ( ((Labelled l | Optional l) as lbl) - , None - , ( { ppat_desc= - ( Ppat_var {txt; loc= _} - | Ppat_constraint - ( { ppat_desc= Ppat_var {txt; loc= _} - ; ppat_attributes= [] - ; _ } - , _ ) ) - ; ppat_attributes= [] - ; _ } as pat ) ) - when String.equal l.txt txt -> - let symbol = match lbl with Labelled _ -> "~" | _ -> "?" in - let xpat = sub_pat ~ctx pat in - cbox 0 (str symbol $ fmt_pattern ~box:true c xpat) - | Pparam_val ((Optional _ as lbl), None, pat) -> - let xpat = sub_pat ~ctx pat in - let has_attr = not (List.is_empty pat.ppat_attributes) in - let outer_parens, inner_parens = - match pat.ppat_desc with - | Ppat_any | Ppat_var _ -> (false, false) - | Ppat_unpack _ -> (not has_attr, true) - | Ppat_tuple _ -> (false, true) - | Ppat_or _ -> (has_attr, true) - | _ -> (not has_attr, false) - in - cbox 2 - ( fmt_label lbl ":@," - $ hovbox 0 - @@ Params.parens_if outer_parens c.conf - (fmt_pattern ~parens:inner_parens c xpat) ) - | Pparam_val (((Labelled _ | Nolabel) as lbl), None, pat) -> - let xpat = sub_pat ~ctx pat in - cbox 2 (fmt_label lbl ":@," $ fmt_pattern c xpat) - | Pparam_val - ( Optional l - , Some exp - , ({ppat_desc= Ppat_var {txt; loc= _}; ppat_attributes= []; _} as pat) - ) - when String.equal l.txt txt -> - let xexp = sub_exp ~ctx exp in - let xpat = sub_pat ~ctx pat in - cbox 0 - (wrap "?(" ")" - ( fmt_pattern c ~box:true xpat - $ fmt " =@;<1 2>" - $ hovbox 2 (fmt_expression c xexp) ) ) - | Pparam_val - ( Optional l - , Some exp - , ( { ppat_desc= - Ppat_constraint ({ppat_desc= Ppat_var {txt; loc= _}; _}, _) - ; ppat_attributes= [] - ; _ } as pat ) ) - when String.equal l.txt txt -> - let xexp = sub_exp ~ctx exp in - let xpat = sub_pat ~ctx pat in - cbox 0 - (wrap "?(" ")" - ( fmt_pattern c ~parens:false ~box:true xpat - $ fmt " =@;<1 2>" $ fmt_expression c xexp ) ) - | Pparam_val (Optional l, Some exp, pat) -> - let xexp = sub_exp ~ctx exp in - let xpat = sub_pat ~ctx pat in - let parens = - match xpat.ast.ppat_desc with - | Ppat_unpack _ -> None - | _ -> Some false - in - cbox 2 - ( str "?" $ str l.txt - $ wrap_k (fmt ":@,(") (str ")") - ( fmt_pattern c ?parens ~box:true xpat - $ fmt " =@;<1 2>" $ fmt_expression c xexp ) ) - | Pparam_val ((Labelled _ | Nolabel), Some _, _) -> - impossible "not accepted by parser" - | Pparam_newtype [] -> impossible "not accepted by parser" - | Pparam_newtype names -> - cbox 0 - (Params.parens c.conf - (str "type " $ list names "@ " (fmt_str_loc c)) ) - in - list args "@;" fmt_fun_arg +and fmt_param_val c ctx : param_val -> _ = function + | ( ((Labelled l | Optional l) as lbl) + , None + , ( { ppat_desc= + ( Ppat_var {txt; loc= _} + | Ppat_constraint + ( {ppat_desc= Ppat_var {txt; loc= _}; ppat_attributes= []; _} + , _ ) ) + ; ppat_attributes= [] + ; _ } as pat ) ) + when String.equal l.txt txt -> + let symbol = match lbl with Labelled _ -> "~" | _ -> "?" in + let xpat = sub_pat ~ctx pat in + cbox 0 (str symbol $ fmt_pattern ~box:true c xpat) + | (Optional _ as lbl), None, pat -> + let xpat = sub_pat ~ctx pat in + let has_attr = not (List.is_empty pat.ppat_attributes) in + let outer_parens, inner_parens = + match pat.ppat_desc with + | Ppat_any | Ppat_var _ -> (false, false) + | Ppat_unpack _ -> (not has_attr, true) + | Ppat_tuple _ -> (false, true) + | Ppat_or _ -> (has_attr, true) + | _ -> (not has_attr, false) + in + cbox 2 + ( fmt_label lbl ":@," + $ hovbox 0 + @@ Params.parens_if outer_parens c.conf + (fmt_pattern ~parens:inner_parens c xpat) ) + | ((Labelled _ | Nolabel) as lbl), None, pat -> + let xpat = sub_pat ~ctx pat in + cbox 2 (fmt_label lbl ":@," $ fmt_pattern c xpat) + | ( Optional l + , Some exp + , ({ppat_desc= Ppat_var {txt; loc= _}; ppat_attributes= []; _} as pat) ) + when String.equal l.txt txt -> + let xexp = sub_exp ~ctx exp in + let xpat = sub_pat ~ctx pat in + cbox 0 + (wrap "?(" ")" + ( fmt_pattern c ~box:true xpat + $ fmt " =@;<1 2>" + $ hovbox 2 (fmt_expression c xexp) ) ) + | ( Optional l + , Some exp + , ( { ppat_desc= + Ppat_constraint ({ppat_desc= Ppat_var {txt; loc= _}; _}, _) + ; ppat_attributes= [] + ; _ } as pat ) ) + when String.equal l.txt txt -> + let xexp = sub_exp ~ctx exp in + let xpat = sub_pat ~ctx pat in + cbox 0 + (wrap "?(" ")" + ( fmt_pattern c ~parens:false ~box:true xpat + $ fmt " =@;<1 2>" $ fmt_expression c xexp ) ) + | Optional l, Some exp, pat -> + let xexp = sub_exp ~ctx exp in + let xpat = sub_pat ~ctx pat in + let parens = + match xpat.ast.ppat_desc with + | Ppat_unpack _ -> None + | _ -> Some false + in + cbox 2 + ( str "?" $ str l.txt + $ wrap_k (fmt ":@,(") (str ")") + ( fmt_pattern c ?parens ~box:true xpat + $ fmt " =@;<1 2>" $ fmt_expression c xexp ) ) + | (Labelled _ | Nolabel), Some _, _ -> impossible "not accepted by parser" + +and fmt_param_newtype c : param_newtype -> _ = function + | [] -> impossible "not accepted by parser" + | names -> + cbox 0 + (Params.parens c.conf + (str "type " $ list names "@ " (fmt_str_loc c)) ) + +and fmt_expr_fun_arg c fp = + let ctx = Fpe fp in + Cmts.fmt c fp.pparam_loc + @@ + match fp.pparam_desc with + | Param_val x -> fmt_param_val c ctx x + | Param_newtype x -> fmt_param_newtype c x + +and fmt_class_fun_arg c fp = + let ctx = Fpc fp in + Cmts.fmt c fp.pparam_loc @@ fmt_param_val c ctx fp.pparam_desc + +and fmt_expr_fun_args c args = list args "@;" (fmt_expr_fun_arg c) + +and fmt_class_fun_args c args = list args "@;" (fmt_class_fun_arg c) (** The second returned value of [fmt_body] belongs to a box of level N-1 if the first returned value belongs to a box of level N. *) @@ -1442,7 +1446,7 @@ and fmt_fun ?force_closing_paren $ fmt "fun" $ break_fun $ hvbox 0 ( fmt_attributes c ast.pexp_attributes ~suf:" " - $ fmt_fun_args c xargs $ fmt_opt fmt_cstr + $ fmt_expr_fun_args c xargs $ fmt_opt fmt_cstr $ fmt "@;<1 -2>->" ) ) ) ) $ body $ closing $ Cmts.fmt_after c ast.pexp_loc ) @@ -1762,7 +1766,7 @@ and fmt_expression c ?(box = true) ?(pro = noop) ?eol ?parens $ hovbox 2 ( fmt_str_loc c name $ str " fun " $ fmt_attributes c ~suf:" " call.pexp_attributes - $ fmt_fun_args c xargs $ fmt_opt fmt_cstr + $ fmt_expr_fun_args c xargs $ fmt_opt fmt_cstr $ fmt "@ ->" ) $ fmt "@ " $ fmt_expression c xbody ) ) $ fmt "@ ;@ " @@ -1792,7 +1796,7 @@ and fmt_expression c ?(box = true) ?(pro = noop) ?eol ?parens $ hovbox 2 ( fmt_str_loc c name $ str " fun " $ fmt_attributes c ~suf:" " retn.pexp_attributes - $ fmt_fun_args c xargs $ fmt_opt fmt_cstr + $ fmt_expr_fun_args c xargs $ fmt_opt fmt_cstr $ fmt "@ ->" ) $ fmt "@ " $ fmt_expression c xbody ) ) ) ) | Pexp_infix ({txt= ":="; loc}, r, v) @@ -1876,7 +1880,8 @@ and fmt_expression c ?(box = true) ?(pro = noop) ?eol ?parens $ hvbox_if (not c.conf.fmt_opts.wrap_fun_args.v) 4 - (fmt_fun_args c xargs $ fmt_opt fmt_cstr) + ( fmt_expr_fun_args c xargs + $ fmt_opt fmt_cstr ) $ fmt "@ ->" ) ) $ pre_body ) $ fmt_or followed_by_infix_op "@;<1000 0>" "@ " @@ -2224,7 +2229,7 @@ and fmt_expression c ?(box = true) ?(pro = noop) ?eol ?parens $ fmt_extension_suffix c ext $ str " " $ fmt_attributes c pexp_attributes ~suf:" " - and args = fmt_fun_args c xargs in + and args = fmt_expr_fun_args c xargs in Params.Exp.box_fun_decl_args c.conf ~parens ~kw ~args ~annot:fmt_cstr in pro @@ -2950,7 +2955,7 @@ and fmt_class_expr c ({ast= exp; ctx= ctx0} as xexp) = ( box_fun_decl_args c 0 ( str "fun " $ fmt_attributes c pcl_attributes ~suf:" " - $ wrap_fun_decl_args c (fmt_fun_args c xargs) + $ wrap_fun_decl_args c (fmt_class_fun_args c xargs) $ fmt "@ " ) $ str "->" ) $ fmt "@ " @@ -3044,7 +3049,7 @@ and fmt_class_field_kind c ctx = function ~after:e.ast.pexp_loc ; ( noop , fmt_if (not (List.is_empty xargs)) "@ " - $ wrap_fun_decl_args c (fmt_fun_args c xargs) + $ wrap_fun_decl_args c (fmt_expr_fun_args c xargs) $ opt ty (fun t -> fmt "@ : " $ fmt_core_type c (sub_typ ~ctx t)) , fmt "@;<1 2>=" , fmt "@ " $ fmt_expression c e ) @@ -3803,7 +3808,7 @@ and fmt_class_exprs ?ext c cls = $ fmt_class_params c ctx cl.pci_params $ fmt_str_loc c cl.pci_name ) $ fmt_if (not (List.is_empty xargs)) "@ " - $ wrap_fun_decl_args c (fmt_fun_args c xargs) ) + $ wrap_fun_decl_args c (fmt_class_fun_args c xargs) ) in let intro = match cl.pci_constraint with @@ -4473,7 +4478,7 @@ and fmt_value_binding c ~rec_flag ?ext ?in_ ?epi and args = fmt_if_k (not (List.is_empty lb_args)) - (fmt "@ " $ wrap_fun_decl_args c (fmt_fun_args c lb_args)) + (fmt "@ " $ wrap_fun_decl_args c (fmt_expr_fun_args c lb_args)) $ fmt_newtypes in box_fun_decl_args c 4 (Params.Align.fun_decl c.conf ~decl ~pattern ~args) diff --git a/lib/Sugar.ml b/lib/Sugar.ml index 991227be36..3706d968a8 100644 --- a/lib/Sugar.ml +++ b/lib/Sugar.ml @@ -14,10 +14,6 @@ open Asttypes open Ast open Extended_ast -let mk_function_param {Location.loc_start; _} {Location.loc_end; _} p = - let pparam_loc = {Location.loc_start; loc_end; loc_ghost= true} in - {pparam_desc= p; pparam_loc} - let fun_ cmts ?(will_keep_first_ast_node = true) xexp = let rec fun_ ?(will_keep_first_ast_node = false) ({ast= exp; _} as xexp) = let ctx = Exp exp in @@ -30,21 +26,6 @@ let fun_ cmts ?(will_keep_first_ast_node = true) xexp = ~after:body.pexp_loc ; let xargs, xbody = fun_ (sub_exp ~ctx body) in (p :: xargs, xbody) - | Pexp_newtype (name, body) -> - if not will_keep_first_ast_node then - Cmts.relocate cmts ~src:pexp_loc ~before:body.pexp_loc - ~after:body.pexp_loc ; - let xargs, xbody = fun_ (sub_exp ~ctx body) in - let xargs = - match xargs with - | {pparam_desc= Pparam_newtype names; pparam_loc} :: xargs -> - let param = Pparam_newtype (name :: names) in - mk_function_param name.loc pparam_loc param :: xargs - | xargs -> - let param = Pparam_newtype [name] in - mk_function_param name.loc name.loc param :: xargs - in - (xargs, xbody) | _ -> ([], xexp) else ([], xexp) in @@ -161,7 +142,7 @@ module Let_binding = struct type t = { lb_op: string loc ; lb_pat: pattern xt - ; lb_args: function_param list + ; lb_args: expr_function_param list ; lb_typ: value_constraint option ; lb_exp: expression xt ; lb_pun: bool @@ -182,7 +163,7 @@ module Let_binding = struct [Extended_ast]. *) let pat = Ast_helper.Pat.any () in let param = - { pparam_desc= Pparam_val (Nolabel, None, pat) + { pparam_desc= Param_val (Nolabel, None, pat) ; pparam_loc= pat.ppat_loc } in Exp (Ast_helper.Exp.fun_ param exp) diff --git a/lib/Sugar.mli b/lib/Sugar.mli index 0660531527..bc5932cea8 100644 --- a/lib/Sugar.mli +++ b/lib/Sugar.mli @@ -17,7 +17,7 @@ val fun_ : Cmts.t -> ?will_keep_first_ast_node:bool -> expression Ast.xt - -> function_param list * expression Ast.xt + -> expr_function_param list * expression Ast.xt (** [fun_ cmts will_keep_first_ast_node exp] returns the list of arguments and the body of the function [exp]. [will_keep_first_ast_node] is set by default, otherwise the [exp] is returned without modification. *) @@ -49,7 +49,7 @@ module Let_binding : sig type t = { lb_op: string loc ; lb_pat: pattern Ast.xt - ; lb_args: function_param list + ; lb_args: expr_function_param list ; lb_typ: value_constraint option ; lb_exp: expression Ast.xt ; lb_pun: bool diff --git a/test/passing/dune.inc b/test/passing/dune.inc index f4b5434f61..717fda4ea1 100644 --- a/test/passing/dune.inc +++ b/test/passing/dune.inc @@ -1136,7 +1136,7 @@ (action (with-stdout-to comments-no-wrap.ml.stdout (with-stderr-to comments-no-wrap.ml.stderr - (run %{bin:ocamlformat} --margin-check --no-wrap-comments --max-iter=3 %{dep:tests/comments.ml}))))) + (run %{bin:ocamlformat} --margin-check --no-wrap-comments --max-iter=4 %{dep:tests/comments.ml}))))) (rule (alias runtest) diff --git a/test/passing/tests/comments-no-wrap.ml.opts b/test/passing/tests/comments-no-wrap.ml.opts index 4fa0ab82c2..5c3491a27b 100644 --- a/test/passing/tests/comments-no-wrap.ml.opts +++ b/test/passing/tests/comments-no-wrap.ml.opts @@ -1,2 +1,2 @@ --no-wrap-comments ---max-iter=3 +--max-iter=4 diff --git a/test/passing/tests/comments-no-wrap.ml.ref b/test/passing/tests/comments-no-wrap.ml.ref index 0d015cf693..1f8f885b97 100644 --- a/test/passing/tests/comments-no-wrap.ml.ref +++ b/test/passing/tests/comments-no-wrap.ml.ref @@ -454,3 +454,9 @@ let _ = (* indentation not preserved *) () + +let vexpr (*aa*) + (type (*bb*) a + (*cc*) + (*dd*) b ) : _ -> _ = + (*ee*) k diff --git a/test/passing/tests/comments.ml b/test/passing/tests/comments.ml index eb247663d4..bab8d067fd 100644 --- a/test/passing/tests/comments.ml +++ b/test/passing/tests/comments.ml @@ -330,3 +330,5 @@ let _ = (* indentation not preserved *) () + +let vexpr (*aa*) (type (*bb*) a) (*cc*) (type (*dd*) b) (*ee*) : _ -> _ = k diff --git a/test/passing/tests/comments.ml.ref b/test/passing/tests/comments.ml.ref index e7c66948bf..31a79cce3d 100644 --- a/test/passing/tests/comments.ml.ref +++ b/test/passing/tests/comments.ml.ref @@ -453,3 +453,9 @@ let _ = () ; (* indentation not preserved *) () + +let vexpr (*aa*) + (type (*bb*) a + (*cc*) + (*dd*) b ) : _ -> _ = + (*ee*) k diff --git a/vendor/parser-extended/ast_mapper.ml b/vendor/parser-extended/ast_mapper.ml index 320c836cad..dcbb16dcf0 100644 --- a/vendor/parser-extended/ast_mapper.ml +++ b/vendor/parser-extended/ast_mapper.ml @@ -114,19 +114,24 @@ let map_value_constraint sub = function let coercion = sub.typ sub coercion in Pvc_coercion { ground; coercion } -let map_function_param sub { pparam_loc = loc; pparam_desc = desc } = - let loc = sub.location sub loc in - let desc = - match desc with - | Pparam_val (lab, def, p) -> - Pparam_val - (sub.arg_label sub lab, - map_opt (sub.expr sub) def, - sub.pat sub p) - | Pparam_newtype ty -> - Pparam_newtype (List.map (map_loc sub) ty) - in - { pparam_loc = loc; pparam_desc = desc } +module FP = struct + let map_param_val sub ((lab, def, p) : param_val) : param_val = + (sub.arg_label sub lab, map_opt (sub.expr sub) def, sub.pat sub p) + + let map_param_newtype sub (ty : param_newtype) : param_newtype = + List.map (map_loc sub) ty + + let map_expr sub = function + | Param_val x -> Param_val (map_param_val sub x) + | Param_newtype x -> Param_newtype (map_param_newtype sub x) + + let map_class sub x = map_param_val sub x + + let map sub f { pparam_loc; pparam_desc } = + let pparam_loc = sub.location sub pparam_loc in + let pparam_desc = f sub pparam_desc in + { pparam_loc; pparam_desc } +end module Flag = struct open Asttypes @@ -514,7 +519,7 @@ module E = struct (sub.expr sub e) | Pexp_fun (p, e) -> fun_ ~loc ~attrs - (map_function_param sub p) + (FP.map sub FP.map_expr p) (sub.expr sub e) | Pexp_function pel -> function_ ~loc ~attrs (sub.cases sub pel) | Pexp_apply (e, l) -> @@ -694,7 +699,7 @@ module CE = struct structure ~loc ~attrs (sub.class_structure sub s) | Pcl_fun (p, ce) -> fun_ ~loc ~attrs - (List.map (map_function_param sub) p) + (List.map (FP.map sub FP.map_class) p) (sub.class_expr sub ce) | Pcl_apply (ce, l) -> apply ~loc ~attrs (sub.class_expr sub ce) @@ -745,7 +750,7 @@ module CE = struct Ci.mk ~loc ~attrs ~virt:(Flag.map_virtual sub pci_virt) ~params:(List.map (map_fst (sub.typ sub)) pl) - ~args:(List.map (map_function_param sub) pci_args) + ~args:(List.map (FP.map sub FP.map_class) pci_args) ?constraint_:(map_opt (sub.class_type sub) pci_constraint) (map_loc sub pci_name) (f pci_expr) diff --git a/vendor/parser-extended/parser.mly b/vendor/parser-extended/parser.mly index 5c2ea4992c..2110957111 100644 --- a/vendor/parser-extended/parser.mly +++ b/vendor/parser-extended/parser.mly @@ -68,6 +68,7 @@ let mkstr ~loc d = Str.mk ~loc:(make_loc loc) d let mkclass ~loc ?attrs d = Cl.mk ~loc:(make_loc loc) ?attrs d let mkcty ~loc ?attrs d = Cty.mk ~loc:(make_loc loc) ?attrs d let mkconst ~loc c = Const.mk ~loc:(make_loc loc) c +let mkfunparam ~loc x = { pparam_loc = make_loc loc; pparam_desc = x } let pstr_typext (te, ext) = (Pstr_typext te, ext) @@ -858,6 +859,8 @@ The precedences must be listed from low to high. { mkcf ~loc:$sloc $1 } %inline mkclass(symb): symb { mkclass ~loc:$sloc $1 } +%inline mkfunparam(symb): symb + { mkfunparam ~loc:$sloc $1 } %inline wrap_mkstr_ext(symb): symb { wrap_mkstr_ext ~loc:$sloc $1 } @@ -1802,7 +1805,7 @@ module_type_subst: ; class_fun_binding: - params = list(fun_param) + params = list(class_fun_param) ct = ioption(COLON class_type { $2 }) EQUAL ce = class_expr @@ -1859,7 +1862,7 @@ class_simple_expr: class_fun_def: mkclass( - nonempty_llist(fun_param) MINUSGREATER e = class_expr + nonempty_llist(class_fun_param) MINUSGREATER e = class_expr { Pcl_fun($1, e) } ) { $1 } ; @@ -2265,10 +2268,8 @@ expr: Pexp_letopen(od, $7), $4 } | FUNCTION ext_attributes match_cases { Pexp_function $3, $2 } - | FUN ext_attributes fun_param fun_def + | FUN ext_attributes expr_fun_param fun_def { Pexp_fun($3, $4), $2 } - | FUN ext_attributes LPAREN TYPE lident_list RPAREN fun_def - { (mk_newtypes ~loc:$sloc $5 $7).pexp_desc, $2 } | MATCH ext_attributes seq_expr WITH match_cases { Pexp_match($3, $5), $2 } | TRY ext_attributes seq_expr WITH match_cases @@ -2574,10 +2575,8 @@ fun_binding: strict_binding: EQUAL seq_expr { $2 } - | fun_param fun_binding + | expr_fun_param fun_binding { ghexp ~loc:$sloc (Pexp_fun($1, $2)) } - | LPAREN TYPE lident_list RPAREN fun_binding - { mk_newtypes ~loc:$sloc $3 $5 } ; %inline match_cases: xs = preceded_or_separated_nonempty_llist(BAR, match_case) @@ -2591,10 +2590,24 @@ match_case: | pattern MINUSGREATER DOT { Exp.case $1 (Exp.unreachable ~loc:(make_loc $loc($3)) ()) } ; -fun_param: +param_val: | labeled_simple_pattern - { let l, o, p = $1 in - { pparam_loc = make_loc $sloc; pparam_desc = Pparam_val (l, o, p) } } + { $1 } +; +param_newtype: + | LPAREN TYPE lident_list RPAREN + { $3 } +; +expr_fun_param: + mkfunparam( + param_val { Param_val $1 } + | param_newtype { Param_newtype $1 } + ) { $1 } +; +class_fun_param: + mkfunparam ( + param_val { $1 } + ) { $1 } ; fun_def: MINUSGREATER seq_expr @@ -2603,10 +2616,8 @@ fun_def: { Pexp_constraint ($4, $2) }) { $1 } /* Cf #5939: we used to accept (fun p when e0 -> e) */ - | fun_param fun_def + | expr_fun_param fun_def { ghexp ~loc:$sloc (Pexp_fun($1, $2)) } - | LPAREN TYPE lident_list RPAREN fun_def - { mk_newtypes ~loc:$sloc $3 $5 } ; %inline expr_comma_list: es = separated_nontrivial_llist(COMMA, expr) diff --git a/vendor/parser-extended/parsetree.mli b/vendor/parser-extended/parsetree.mli index cd430ce1a3..af612dcae1 100644 --- a/vendor/parser-extended/parsetree.mli +++ b/vendor/parser-extended/parsetree.mli @@ -321,7 +321,7 @@ and expression_desc = when [flag] is {{!Asttypes.rec_flag.Recursive}[Recursive]}. *) | Pexp_function of case list (** [function P1 -> E1 | ... | Pn -> En] *) - | Pexp_fun of function_param * expression + | Pexp_fun of expr_function_param * expression (** [Pexp_fun(P, E)] represents: - [fun P -> E] - [fun ~l:P -> E] @@ -488,38 +488,32 @@ and binding_op = pbop_loc : Location.t; } -and function_param_desc = - | Pparam_val of arg_label * expression option * pattern - (** [Pparam_val (lbl, exp0, P)] represents the parameter: - - [P] - when [lbl] is {{!Asttypes.arg_label.Nolabel}[Nolabel]} - and [exp0] is [None] - - [~l:P] - when [lbl] is {{!Asttypes.arg_label.Labelled}[Labelled l]} - and [exp0] is [None] - - [?l:P] - when [lbl] is {{!Asttypes.arg_label.Optional}[Optional l]} - and [exp0] is [None] - - [?l:(P = E0)] - when [lbl] is {{!Asttypes.arg_label.Optional}[Optional l]} - and [exp0] is [Some E0] - - Note: If [E0] is provided, only - {{!Asttypes.arg_label.Optional}[Optional]} is allowed. - *) - | Pparam_newtype of string loc list - (** [Pparam_newtype x] represents the parameter [(type x y z)]. - [x] carries the location of the identifier, whereas the [pparam_loc] - on the enclosing [function_param] node is the location of the [(type x y z)] - as a whole. +and param_val = arg_label * expression option * pattern + (** - [P] when [lbl] is [Nolabel] and [exp0] is [None] + - [~l:P] when [lbl] is [Labelled l] and [exp0] is [None] + - [?l:P] when [lbl] is [Optional l] and [exp0] is [None] + - [?l:(P = E0)] when [lbl] is [Optional l] and [exp0] is [Some E0] + + Note: If [E0] is provided, only [Optional] is allowed. *) -and function_param = +and param_newtype = string loc list + (** [(type x y z)]. *) + +and 'a function_param = { pparam_loc : Location.t; - pparam_desc : function_param_desc; + pparam_desc : 'a; } +and param_val_or_newtype = + | Param_val of param_val + | Param_newtype of param_newtype + +and expr_function_param = param_val_or_newtype function_param + +and class_function_param = param_val function_param + and type_constraint = | Pconstraint of core_type | Pcoerce of core_type option * core_type @@ -750,7 +744,7 @@ and 'a class_infos = pci_virt: virtual_flag; pci_params: (core_type * variance_and_injectivity) list; pci_name: string loc; - pci_args: function_param list; + pci_args: class_function_param list; pci_constraint: class_type option; pci_expr: 'a; pci_loc: Location.t; @@ -781,7 +775,7 @@ and class_expr_desc = | Pcl_constr of Longident.t loc * core_type list (** [c] and [['a1, ..., 'an] c] *) | Pcl_structure of class_structure (** [object ... end] *) - | Pcl_fun of function_param list * class_expr + | Pcl_fun of class_function_param list * class_expr (** [Pcl_fun(P, CE)] represents: - [fun P -> CE] - [fun ~l:P -> CE] diff --git a/vendor/parser-extended/printast.ml b/vendor/parser-extended/printast.ml index 42249bb26e..7ce7ee1848 100644 --- a/vendor/parser-extended/printast.ml +++ b/vendor/parser-extended/printast.ml @@ -347,7 +347,7 @@ and expression i ppf x = list i case ppf l; | Pexp_fun (p, e) -> line i ppf "Pexp_fun\n"; - function_param i ppf p; + expr_function_param i ppf p; expression i ppf e; | Pexp_apply (e, l) -> line i ppf "Pexp_apply\n"; @@ -512,17 +512,25 @@ and if_branch i ppf { if_cond; if_body } = expression i ppf if_cond; expression i ppf if_body -and function_param i ppf { pparam_desc = desc; pparam_loc = loc } = +and param_val i ppf (l, eo, p) = + line i ppf "param_val\n"; + arg_label (i+1) ppf l; + option (i+1) expression ppf eo; + pattern (i+1) ppf p + +and param_newtype i ppf ty = + line i ppf "param_newtype\n"; + list i (fun i ppf x -> line (i+1) ppf "type %a" fmt_string_loc x) ppf ty + +and expr_function_param i ppf { pparam_desc = desc; pparam_loc = loc } = + line i ppf "function_param %a\n" fmt_location loc; match desc with - | Pparam_val (l, eo, p) -> - line i ppf "Pparam_val %a\n" fmt_location loc; - arg_label (i+1) ppf l; - option (i+1) expression ppf eo; - pattern (i+1) ppf p - | Pparam_newtype ty -> - line i ppf "Pparam_newtype %a\n" fmt_location loc; - list i (fun i ppf x -> - line (i+1) ppf "type %a" fmt_string_loc x ) ppf ty + | Param_val x -> param_val i ppf x + | Param_newtype x -> param_newtype i ppf x + +and class_function_param i ppf { pparam_desc = desc; pparam_loc = loc } = + line i ppf "function_param %a\n" fmt_location loc; + param_val i ppf desc and type_constraint i ppf constraint_ = match constraint_ with @@ -704,7 +712,7 @@ and class_infos : 'a. _ -> (_ -> _ -> 'a -> _) -> _ -> _ -> 'a class_infos -> _ list (i+1) type_parameter ppf x.pci_params; line i ppf "pci_name = %a\n" fmt_string_loc x.pci_name; line i ppf "pci_args =\n"; - list (i+1) function_param ppf x.pci_args; + list (i+1) class_function_param ppf x.pci_args; line i ppf "pci_constraint = %a\n" (fmt_opt (class_type i)) x.pci_constraint; line i ppf "pci_expr =\n"; f (i+1) ppf x.pci_expr @@ -726,7 +734,7 @@ and class_expr i ppf x = class_structure i ppf cs; | Pcl_fun (p, e) -> line i ppf "Pcl_fun\n"; - list i function_param ppf p; + list i class_function_param ppf p; class_expr i ppf e; | Pcl_apply (ce, l) -> line i ppf "Pcl_apply\n"; @@ -1212,7 +1220,9 @@ let structure_item ppf x = structure_item 0 ppf x let signature_item ppf x = signature_item 0 ppf x -let function_param ppf x = function_param 0 ppf x +let expr_function_param ppf x = expr_function_param 0 ppf x + +let class_function_param ppf x = class_function_param 0 ppf x let value_constraint ppf x = value_constraint 0 ppf x