Skip to content

Commit cd3c4a0

Browse files
committed
Remove path of value defined in a module inside extracted expr.
1 parent 3627558 commit cd3c4a0

File tree

3 files changed

+76
-4
lines changed

3 files changed

+76
-4
lines changed

src/analysis/refactor_extract_region.ml

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -145,15 +145,15 @@ let rec find_pattern_var : type a. a Typedtree.general_pattern -> Path.t list =
145145
| Tpat_or (l, r, _) -> find_pattern_var l @ find_pattern_var r
146146
| _ -> []
147147

148-
let rec occuring_vars node =
148+
let rec occuring_vars_path node =
149149
let loop acc node =
150150
match node.Browse_tree.t_node with
151151
| Browse_raw.Expression { exp_desc = Texp_ident (path, _, _); _ } ->
152152
path :: acc
153153
| Pattern pat -> find_pattern_var pat @ acc
154154
| _ ->
155155
Lazy.force node.t_children
156-
|> List.concat_map ~f:occuring_vars
156+
|> List.concat_map ~f:occuring_vars_path
157157
|> List.append acc
158158
in
159159
loop [] node |> Path.Set.of_list |> Path.Set.elements |> List.rev
@@ -177,7 +177,7 @@ let analyze_expr expr expr_env ~toplevel_item =
177177
bindings
178178
in
179179
Browse_tree.of_node ~env:expr_env (Browse_raw.Expression expr)
180-
|> occuring_vars
180+
|> occuring_vars_path
181181
|> List.fold_left ~init:{ bounded_vars = []; binding_kind = Non_recursive }
182182
~f:(fun acc var_path ->
183183
if is_value_unbound var_path then
@@ -295,9 +295,23 @@ let extract_expr_to_toplevel ?extract_name expr ~expr_env ~toplevel_item =
295295
| { Typedtree.exp_desc = Texp_function _; _ } -> true
296296
| _ -> false
297297
in
298+
let is_module_bound path =
299+
try
300+
let _ = Env.find_module path toplevel_item.env in
301+
false
302+
with Not_found -> true
303+
in
298304
let { bounded_vars; binding_kind } =
299305
analyze_expr expr expr_env ~toplevel_item
300306
in
307+
let bounded_vars_stamp =
308+
List.map ~f:(fun p -> Path.head p |> Ident.stamp) bounded_vars
309+
in
310+
let is_bound_var path =
311+
List.exists
312+
~f:(Int.equal (Path.head path |> Ident.stamp))
313+
bounded_vars_stamp
314+
in
301315
let generated_binding, generated_call =
302316
match bounded_vars with
303317
| [] when not (is_function expr) ->
@@ -312,8 +326,17 @@ let extract_expr_to_toplevel ?extract_name expr ~expr_env ~toplevel_item =
312326
| None -> Default { basename = "fun_name" }
313327
| Some name -> Fixed name
314328
in
329+
let remove_path_prefix mapper expr =
330+
match expr.Typedtree.exp_desc with
331+
| Texp_ident (Pdot (path, val_name), longident, vd)
332+
when is_bound_var path && is_module_bound path ->
333+
let ident = { longident with txt = Longident.Lident val_name } in
334+
{ expr with exp_desc = Texp_ident (path, ident, vd) }
335+
| _ -> Tast_mapper.default.expr mapper expr
336+
in
337+
let mapper = { Tast_mapper.default with expr = remove_path_prefix } in
315338
extract_to_toplevel
316-
{ expr;
339+
{ expr = mapper.expr mapper expr;
317340
expr_env;
318341
toplevel_item;
319342
name;

tests/test-dirs/refactor-extract-region/func-extraction.t/func.ml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,3 +131,16 @@ let pp_document ppf doc =
131131
| Text txt -> pp_print_string ppf txt
132132
| Bold txt -> pp_print_string ppf (bold_tag ^ txt ^ bold_tag)))
133133
doc
134+
135+
module A = struct
136+
let a = 10
137+
end
138+
let f x =
139+
let module Empty = struct end in
140+
let module M = struct
141+
module MM = struct
142+
let y = 0
143+
end
144+
let z = 0
145+
end in
146+
x * M.z * M.MM.y + A.a

tests/test-dirs/refactor-extract-region/func-extraction.t/run.t

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -727,3 +727,39 @@ TODO: This extraction shouldn't be allowed.
727727
},
728728
"notifications": []
729729
}
730+
731+
$ $MERLIN single refactoring-extract-region -start 146:2 -end 146:25 -extract-name add < func.ml
732+
{
733+
"class": "return",
734+
"value": {
735+
"start": {
736+
"line": 138,
737+
"col": 0
738+
},
739+
"end": {
740+
"line": 146,
741+
"col": 24
742+
},
743+
"content": "let add (x) (z) (y) = ((x * z) * y) + A.a
744+
let f x =
745+
let module Empty = struct end in
746+
let module M = struct
747+
module MM = struct
748+
let y = 0
749+
end
750+
let z = 0
751+
end in
752+
(add x M.z M.MM.y)",
753+
"selection-range": {
754+
"start": {
755+
"line": 138,
756+
"col": 4
757+
},
758+
"end": {
759+
"line": 138,
760+
"col": 7
761+
}
762+
}
763+
},
764+
"notifications": []
765+
}

0 commit comments

Comments
 (0)