-
Notifications
You must be signed in to change notification settings - Fork 57
/
Copy pathCodemod.ml
47 lines (45 loc) · 1.72 KB
/
Codemod.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
type transformType = AddMissingCases
let rec collectPatterns p =
match p.Parsetree.ppat_desc with
| Ppat_or (p1, p2) -> collectPatterns p1 @ [p2]
| _ -> [p]
let transform ~path ~pos ~debug ~typ ~hint =
let structure, printExpr, _, _ = Xform.parseImplementation ~filename:path in
match typ with
| AddMissingCases -> (
let source = "let " ^ hint ^ " = ()" in
let {Res_driver.parsetree = hintStructure} =
Res_driver.parse_implementation_from_source ~for_printer:false
~display_filename:"<none>" ~source
in
match hintStructure with
| [{pstr_desc = Pstr_value (_, [{pvb_pat = pattern}])}] -> (
let cases =
collectPatterns pattern
|> List.map (fun (p : Parsetree.pattern) ->
Ast_helper.Exp.case p (TypeUtils.Codegen.mkFailWithExp ()))
in
let result = ref None in
let mkIterator ~pos ~result =
let expr (iterator : Ast_iterator.iterator) (exp : Parsetree.expression)
=
match exp.pexp_desc with
| Pexp_match (e, existingCases)
when Pos.ofLexing exp.pexp_loc.loc_start = pos ->
result :=
Some {exp with pexp_desc = Pexp_match (e, existingCases @ cases)}
| _ -> Ast_iterator.default_iterator.expr iterator exp
in
{Ast_iterator.default_iterator with expr}
in
let iterator = mkIterator ~pos ~result in
iterator.structure iterator structure;
match !result with
| None ->
if debug then print_endline "Found no result";
exit 1
| Some switchExpr ->
printExpr ~range:(Loc.rangeOfLoc switchExpr.pexp_loc) switchExpr)
| _ ->
if debug then print_endline "Mismatch in expected structure";
exit 1)