Source file refactor_open.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
48
49
50
open Std
(** [qual_or_unqual_path mode ~open_lident ~open_path node_path node_lid]
if mode is
`Unqualify - returns [node_lid] or [node_lid] with prefix [open_lident] cut off,
whichever is shorter
`Qualify - returns [node_path] with its prefix equal to [open_lident]
Returns [None] if [node_lid] doesn't need changes.
Note: by "prefix" we mean the leftmost consecutive part of a longident or a path. *)
let qual_or_unqual_path mode ~open_lident ~open_path node_path node_lid =
let open_lid_head = Longident.head open_lident in
let node_lid_head = Longident.head node_lid in
let rec make_new_node_lid acc (p : Path.t) =
match p with
| Pident ident -> Ident.name ident :: acc
| Pdot (path', s)
when mode = `Unqualify
&& (Path.same open_path path'
|| String.equal s
node_lid_head ) ->
s :: acc
| Pdot (_, s) when mode = `Qualify && s = open_lid_head -> s :: acc
| Pdot (path', s) -> make_new_node_lid (s :: acc) path'
| _ -> raise Not_found
in
let same_longident node_lid_head new_node_lid =
String.equal node_lid_head (List.hd new_node_lid)
in
match make_new_node_lid [] node_path with
| new_node_lid when not (same_longident node_lid_head new_node_lid) ->
Some (String.concat ~sep:"." new_node_lid)
| _ | (exception Not_found) -> None
let get_rewrites ~mode typer pos =
match Mbrowse.select_open_node (Mtyper.node_at typer pos) with
| None | Some (_, _, []) -> []
| Some (open_path, open_lident, (_, node) :: _) ->
let paths_and_lids = Browse_tree.all_occurrences_of_prefix open_path node in
List.filter_map paths_and_lids
~f:(fun ({ Location.txt = path; loc }, lid) ->
if loc.Location.loc_ghost || Location_aux.compare_pos pos loc > 0 then
None
else
qual_or_unqual_path mode ~open_lident ~open_path path lid
|> Option.map ~f:(fun new_lid -> (new_lid, loc)))
|> List.sort_uniq ~cmp:(fun (_, l1) (_, l2) -> Location_aux.compare l1 l2)