@@ -104,6 +104,10 @@ module MapperUtils = struct
104104 if Ext_list. is_empty attrs then e
105105 else {e with pexp_attributes = attrs @ e.pexp_attributes}
106106
107+ let attach_attrs_to_pat ~attrs (pat : Parsetree.pattern ) =
108+ if Ext_list. is_empty attrs then pat
109+ else {pat with ppat_attributes = attrs @ pat.ppat_attributes}
110+
107111 (* Apply transforms attached to an expression itself and drop the
108112 transform attributes afterwards. *)
109113 let apply_on_self (e : Parsetree.expression ) : Parsetree.expression =
@@ -332,6 +336,29 @@ module TypeReplace = struct
332336 | _ -> None
333337end
334338
339+ module VariantReplace = struct
340+ type target = {lid : Longident .t Location .loc ; attrs : Parsetree .attributes }
341+
342+ let of_template (expr : Parsetree.expression ) : target option =
343+ match expr.pexp_desc with
344+ | Pexp_extension
345+ ( {txt = " replace.variant" },
346+ PStr
347+ [
348+ {
349+ pstr_desc =
350+ Pstr_eval
351+ ({pexp_desc = Pexp_construct (lid, _); pexp_attributes}, _);
352+ };
353+ ] ) ->
354+ let attrs =
355+ if Ext_list. is_empty expr.pexp_attributes then pexp_attributes
356+ else expr.pexp_attributes @ pexp_attributes
357+ in
358+ Some {lid; attrs}
359+ | _ -> None
360+ end
361+
335362let remap_needed_extensions (mapper : Ast_mapper.mapper )
336363 (ext : Parsetree.extension ) : Parsetree.extension =
337364 match ext with
@@ -551,6 +578,29 @@ let makeMapper (deprecated_used : Cmt_utils.deprecated_used list) =
551578 |> List. iter (fun ({Cmt_utils. source_loc} as d ) ->
552579 Hashtbl. replace loc_to_deprecated_reference source_loc d);
553580
581+ let deprecated_variant_constructors =
582+ deprecated_used
583+ |> List. filter_map (fun (d : Cmt_utils.deprecated_used ) ->
584+ match d.migration_template with
585+ | Some template -> (
586+ match VariantReplace. of_template template with
587+ | Some target -> Some (d.source_loc, target)
588+ | None -> None )
589+ | None -> None )
590+ in
591+ let loc_to_deprecated_variant_constructor =
592+ Hashtbl. create (List. length deprecated_variant_constructors)
593+ in
594+ deprecated_variant_constructors
595+ |> List. iter (fun (loc , target ) ->
596+ Hashtbl. replace loc_to_deprecated_variant_constructor loc target);
597+
598+ let find_variant_target ~loc ~lid_loc =
599+ match Hashtbl. find_opt loc_to_deprecated_variant_constructor loc with
600+ | Some _ as found -> found
601+ | None -> Hashtbl. find_opt loc_to_deprecated_variant_constructor lid_loc
602+ in
603+
554604 (* Helpers for type replacement lookups *)
555605 let loc_contains (a : Location.t ) (b : Location.t ) =
556606 let a_start = a.Location. loc_start.pos_cnum in
@@ -629,6 +679,13 @@ let makeMapper (deprecated_used : Cmt_utils.deprecated_used list) =
629679 match deprecated_info.migration_template with
630680 | Some e -> apply_template_direct mapper e call_args exp
631681 | None -> exp)
682+ | {pexp_desc = Pexp_construct (lid , arg ); pexp_loc} -> (
683+ match find_variant_target ~loc: pexp_loc ~lid_loc: lid.loc with
684+ | Some {VariantReplace. lid; attrs} ->
685+ let arg = Option. map (mapper.expr mapper) arg in
686+ let replaced = {exp with pexp_desc = Pexp_construct (lid, arg)} in
687+ MapperUtils.ApplyTransforms. attach_to_replacement ~attrs replaced
688+ | None -> Ast_mapper. default_mapper.expr mapper exp)
632689 | {
633690 pexp_desc =
634691 Pexp_apply
@@ -664,6 +721,17 @@ let makeMapper (deprecated_used : Cmt_utils.deprecated_used list) =
664721 ~pipe_args ~funct exp
665722 | Some _ -> Ast_mapper. default_mapper.expr mapper exp)
666723 | _ -> Ast_mapper. default_mapper.expr mapper exp);
724+ pat =
725+ (fun mapper pat ->
726+ match pat with
727+ | {ppat_desc = Ppat_construct (lid , arg ); ppat_loc} -> (
728+ match find_variant_target ~loc: ppat_loc ~lid_loc: lid.loc with
729+ | Some {VariantReplace. lid; attrs} ->
730+ let arg = Option. map (mapper.pat mapper) arg in
731+ let replaced = {pat with ppat_desc = Ppat_construct (lid, arg)} in
732+ MapperUtils.ApplyTransforms. attach_attrs_to_pat ~attrs replaced
733+ | None -> Ast_mapper. default_mapper.pat mapper pat)
734+ | _ -> Ast_mapper. default_mapper.pat mapper pat);
667735 }
668736 in
669737 mapper
0 commit comments