Skip to content

Commit 500487f

Browse files
committed
Merge branch 'main' into refactor-extraction
2 parents a7a3729 + 8b88b89 commit 500487f

File tree

32 files changed

+1746
-210
lines changed

32 files changed

+1746
-210
lines changed

.github/workflows/changelog.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@ on:
88
jobs:
99
Changelog-Entry-Check:
1010
name: Check Changelog Action
11-
runs-on: ubuntu-20.04
11+
runs-on: ubuntu-latest
1212
steps:
1313
- uses: tarides/changelog-check-action@v3

.github/workflows/nix.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ jobs:
3131
with:
3232
submodules: true
3333
- name: nix
34-
uses: cachix/install-nix-action@V28
34+
uses: cachix/install-nix-action@31.3.0
3535
with:
3636
nix_path: nixpkgs=channel:nixos-unstable
3737
- run: nix develop -c dune build @check @runtest -p merlin-lib,dot-merlin-reader,ocaml-index,merlin

CHANGES.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
unreleased
1+
merlin 5.5
22
==========
3+
Tue Jun 24 16:10:42 CEST 2025
34

45
+ merlin library
56
- Expose utilities to manipulate typed-holes in `Merlin_analysis.Typed_hole`
@@ -10,6 +11,17 @@ unreleased
1011
- `inlay-hints` fix inlay hints on function parameters (#1923)
1112
- Fix issues with ident validation and Lid comparison for occurrences (#1924)
1213
- Handle class type in outline (#1932)
14+
- Handle locally defined value in outline (#1936)
15+
- Fix a typer issue triggering assertions in the short-paths graph (#1935,
16+
fixes #1913)
17+
- Downstreamed a typer fix from 5.3.X that would trigger assertions linked
18+
to scopes bit masks when backtracking the typer cache (#1935)
19+
- Add a new selection field to outline results that contains the location of
20+
the symbol itself. (#1942)
21+
- Fix destruct hanging when printing patterns with (::). (#1944, fixes
22+
ocaml/ocaml-lsp#1489)
23+
- Reproduce and fix a handful of jump-to-definition (locate) issues (#1930,
24+
fixes #1580 and #1588, workaround for #1934)
1325
+ ocaml-index
1426
- Improve the granularity of index reading by segmenting the marshalization
1527
of the involved data-structures. (#1889)

src/analysis/locate.ml

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -294,14 +294,38 @@ module Utils = struct
294294
| CMT _ | CMTI _ -> Mconfig.cmt_path config
295295
end
296296

297-
let move_to filename cmt_infos =
297+
let reroot_build_dir ~root path =
298+
let sep =
299+
try String.get Filename.dir_sep 0 with Invalid_argument _ -> '/'
300+
in
301+
let segments = path |> String.split_on_char ~sep in
302+
let rec strip_prefix = function
303+
| [] -> []
304+
| "_build" :: _ as l -> l
305+
| _ :: tl -> strip_prefix tl
306+
in
307+
match strip_prefix segments with
308+
| [] -> path
309+
| l ->
310+
let sep = Printf.sprintf "%c" sep in
311+
Filename.concat root (String.concat ~sep l)
312+
313+
let move_to (config : Mconfig.t) filename cmt_infos =
298314
let digest =
299315
(* [None] only for packs, and we wouldn't have a trie if the cmt was for a
300316
pack. *)
301317
let sourcefile_in_builddir =
302318
Filename.concat cmt_infos.Cmt_format.cmt_builddir
303319
(Option.get cmt_infos.cmt_sourcefile)
304320
in
321+
let sourcefile_in_builddir =
322+
(* This workaround is meant to fix issues with Dune's BUILD_PREFIX_MAP It
323+
will not work when the [_build] folder is not located at the source
324+
root. See [#1934](https://github.com/ocaml/merlin/issues/1934). *)
325+
match config.merlin.source_root with
326+
| None -> sourcefile_in_builddir
327+
| Some root -> reroot_build_dir ~root sourcefile_in_builddir
328+
in
305329
match
306330
sourcefile_in_builddir |> String.split_on_char ~sep:'.' |> List.rev
307331
with
@@ -332,7 +356,7 @@ let load_cmt ~config ?(with_fallback = true) comp_unit =
332356
let cmt_infos = (Cmt_cache.read path).cmt_infos in
333357
let source_file = cmt_infos.cmt_sourcefile in
334358
let source_file = Option.value ~default:"*pack*" source_file in
335-
move_to path cmt_infos;
359+
move_to config.mconfig path cmt_infos;
336360
Ok (source_file, cmt_infos)
337361
| None -> Error ()
338362

@@ -622,13 +646,14 @@ let find_loc_of_comp_unit ~config uid comp_unit =
622646

623647
let find_loc_of_uid ~config ~local_defs ?ident ?fallback (uid : Shape.Uid.t) =
624648
let find_loc_of_item ~comp_unit =
625-
match find_loc_of_item ~config ~local_defs uid comp_unit, fallback, ident with
649+
match
650+
(find_loc_of_item ~config ~local_defs uid comp_unit, fallback, ident)
651+
with
626652
| Some { loc; txt }, _, Some ident when String.equal txt ident ->
627653
(* Checking the ident prevent returning nonsensical results when some uid
628654
were swaped but the cmt files were not rebuilt. *)
629655
Some (uid, loc)
630-
| Some { loc; _ }, _, None ->
631-
Some (uid, loc)
656+
| Some { loc; _ }, _, None -> Some (uid, loc)
632657
| (Some _ | None), Some fallback, _ ->
633658
find_loc_of_item ~config ~local_defs fallback comp_unit
634659
|> Option.map ~f:(fun { Location.loc; _ } -> (fallback, loc))
@@ -672,7 +697,7 @@ let find_definition_uid ~config ~env ~(decl : Env_lookup.item) path =
672697
~with_fallback:false unit_name
673698
with
674699
| Ok (filename, cmt_infos) ->
675-
move_to filename cmt_infos;
700+
move_to config.mconfig filename cmt_infos;
676701
log ~title:"read_unit_shape" "shapes loaded for %s" unit_name;
677702
cmt_infos.cmt_impl_shape
678703
| Error () ->

src/analysis/outline.ml

Lines changed: 49 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -35,16 +35,18 @@ open Typedtree
3535
open Browse_raw
3636
open Browse_tree
3737

38-
let id_of_patt = function
39-
| { pat_desc = Tpat_var (id, _, _); _ } -> Some id
38+
let name_of_patt = function
39+
| { pat_desc = Tpat_var (_, name, _); _ } -> Some name
4040
| _ -> None
4141

42-
let mk ?(children = []) ~location ~deprecated outline_kind outline_type id =
42+
let mk ?(children = []) ~location ~deprecated outline_kind outline_type
43+
(name : string Location.loc) =
4344
{ Query_protocol.outline_kind;
4445
outline_type;
4546
location;
47+
selection = name.loc;
4648
children;
47-
outline_name = Ident.name id;
49+
outline_name = name.txt;
4850
deprecated
4951
}
5052

@@ -69,38 +71,38 @@ let rec summarize node =
6971
in
7072
let deprecated = Type_utils.is_deprecated vb.vb_attributes in
7173
begin
72-
match id_of_patt vb.vb_pat with
74+
match name_of_patt vb.vb_pat with
7375
| None -> None
74-
| Some ident ->
76+
| Some name ->
7577
let typ = outline_type ~env:node.t_env vb.vb_pat.pat_type in
76-
Some (mk ~children ~location ~deprecated `Value typ ident)
78+
Some (mk ~children ~location ~deprecated `Value typ name)
7779
end
7880
| Value_description vd ->
7981
let deprecated = Type_utils.is_deprecated vd.val_attributes in
8082
let typ = outline_type ~env:node.t_env vd.val_val.val_type in
81-
Some (mk ~location ~deprecated `Value typ vd.val_id)
83+
Some (mk ~location ~deprecated `Value typ vd.val_name)
8284
| Module_declaration md ->
8385
let children = get_mod_children node in
8486
begin
85-
match md.md_id with
86-
| None -> None
87-
| Some id ->
87+
match md.md_name with
88+
| { txt = None; _ } -> None
89+
| { txt = Some txt; loc } ->
8890
let deprecated = Type_utils.is_deprecated md.md_attributes in
89-
Some (mk ~children ~location ~deprecated `Module None id)
91+
Some (mk ~children ~location ~deprecated `Module None { txt; loc })
9092
end
9193
| Module_binding mb ->
9294
let children = get_mod_children node in
9395
begin
94-
match mb.mb_id with
95-
| None -> None
96-
| Some id ->
96+
match mb.mb_name with
97+
| { txt = None; _ } -> None
98+
| { txt = Some txt; loc } ->
9799
let deprecated = Type_utils.is_deprecated mb.mb_attributes in
98-
Some (mk ~children ~location ~deprecated `Module None id)
100+
Some (mk ~children ~location ~deprecated `Module None { txt; loc })
99101
end
100102
| Module_type_declaration mtd ->
101103
let children = get_mod_children node in
102104
let deprecated = Type_utils.is_deprecated mtd.mtd_attributes in
103-
Some (mk ~deprecated ~children ~location `Modtype None mtd.mtd_id)
105+
Some (mk ~deprecated ~children ~location `Modtype None mtd.mtd_name)
104106
| Type_declaration td ->
105107
let children =
106108
List.concat_map (Lazy.force node.t_children) ~f:(fun child ->
@@ -110,15 +112,15 @@ let rec summarize node =
110112
match x.t_node with
111113
| Constructor_declaration c ->
112114
let deprecated = Type_utils.is_deprecated c.cd_attributes in
113-
mk `Constructor None c.cd_id ~deprecated ~location:c.cd_loc
115+
mk `Constructor None c.cd_name ~deprecated ~location:c.cd_loc
114116
| Label_declaration ld ->
115117
let deprecated = Type_utils.is_deprecated ld.ld_attributes in
116-
mk `Label None ld.ld_id ~deprecated ~location:ld.ld_loc
118+
mk `Label None ld.ld_name ~deprecated ~location:ld.ld_loc
117119
| _ -> assert false (* ! *))
118120
| _ -> [])
119121
in
120122
let deprecated = Type_utils.is_deprecated td.typ_attributes in
121-
Some (mk ~children ~location ~deprecated `Type None td.typ_id)
123+
Some (mk ~children ~location ~deprecated `Type None td.typ_name)
122124
| Type_extension te ->
123125
let name = Path.name te.tyext_path in
124126
let children =
@@ -132,65 +134,58 @@ let rec summarize node =
132134
outline_kind = `Type;
133135
outline_type = None;
134136
location;
137+
selection = te.tyext_txt.loc;
135138
children;
136139
deprecated
137140
}
138141
| Extension_constructor ec ->
139142
let deprecated = Type_utils.is_deprecated ec.ext_attributes in
140-
Some (mk ~location `Exn None ec.ext_id ~deprecated)
143+
Some (mk ~location `Exn None ec.ext_name ~deprecated)
141144
| Class_declaration cd ->
142145
let children =
143146
List.concat_map (Lazy.force node.t_children) ~f:get_class_elements
144147
in
145148
let deprecated = Type_utils.is_deprecated cd.ci_attributes in
146-
Some (mk ~children ~location `Class None cd.ci_id_class_type ~deprecated)
149+
Some (mk ~children ~location `Class None cd.ci_id_name ~deprecated)
147150
| Class_type_declaration ctd ->
148151
let children =
149152
List.concat_map (Lazy.force node.t_children) ~f:get_class_elements
150153
in
151154
let deprecated = Type_utils.is_deprecated ctd.ci_attributes in
152-
Some
153-
(mk ~children ~location `ClassType None ctd.ci_id_class_type ~deprecated)
155+
Some (mk ~children ~location `ClassType None ctd.ci_id_name ~deprecated)
154156
| _ -> None
155157

156158
and get_val_elements node =
157159
match node.t_node with
158160
| Expression _ ->
159161
List.concat_map (Lazy.force node.t_children) ~f:get_val_elements
160-
| Value_binding vb ->
161-
let children =
162-
List.concat_map (Lazy.force node.t_children) ~f:get_val_elements
163-
in
164-
let deprecated = Type_utils.is_deprecated vb.vb_attributes in
165-
begin
166-
match id_of_patt vb.vb_pat with
167-
| None -> []
168-
| Some ident ->
169-
[ mk ~children ~location:node.t_loc ~deprecated `Value None ident ]
170-
end
171162
| Class_expr _ | Class_structure _ -> get_class_elements node
172-
| _ -> []
163+
| _ -> Option.to_list (summarize node)
173164

174165
and get_class_elements node =
175166
match node.t_node with
176167
| Class_expr _ ->
177168
List.concat_map (Lazy.force node.t_children) ~f:get_class_elements
169+
| Class_field cf ->
170+
let children =
171+
List.concat_map (Lazy.force node.t_children) ~f:get_class_elements
172+
in
173+
cf.cf_desc |> get_class_field_desc_infos
174+
|> Option.map ~f:(fun (str_loc, outline_kind) ->
175+
let deprecated = Type_utils.is_deprecated cf.cf_attributes in
176+
{ Query_protocol.outline_name = str_loc.Location.txt;
177+
outline_kind;
178+
outline_type = None;
179+
location = cf.cf_loc;
180+
selection = str_loc.loc;
181+
children;
182+
deprecated
183+
})
184+
|> Option.to_list
185+
| Class_field_kind _ ->
186+
List.concat_map (Lazy.force node.t_children) ~f:get_val_elements
178187
| Class_structure _ ->
179-
List.filter_map (Lazy.force node.t_children) ~f:(fun child ->
180-
match child.t_node with
181-
| Class_field cf -> begin
182-
cf.cf_desc |> get_class_field_desc_infos
183-
|> Option.map ~f:(fun (str_loc, outline_kind, children) ->
184-
let deprecated = Type_utils.is_deprecated cf.cf_attributes in
185-
{ Query_protocol.outline_name = str_loc.Location.txt;
186-
outline_kind;
187-
outline_type = None;
188-
location = str_loc.Location.loc;
189-
children;
190-
deprecated
191-
})
192-
end
193-
| _ -> None)
188+
List.concat_map (Lazy.force node.t_children) ~f:get_class_elements
194189
| Class_type { cltyp_desc = Tcty_signature { csig_fields; _ }; _ } ->
195190
List.filter_map csig_fields ~f:(fun field ->
196191
get_class_signature_field_desc_infos field.ctf_desc
@@ -200,49 +195,18 @@ and get_class_elements node =
200195
outline_kind;
201196
outline_type = None;
202197
location = field.ctf_loc;
198+
selection = field.ctf_loc;
203199
(* TODO: could we have more precised location information? *)
204200
children = [];
205201
deprecated
206202
}))
207203
| _ -> []
208204

209205
and get_class_field_desc_infos = function
210-
| Typedtree.Tcf_val (str_loc, _, _, field_kind, _) ->
211-
Some (str_loc, `Value, get_class_field_kind_elements field_kind)
212-
| Typedtree.Tcf_method (str_loc, _, field_kind) ->
213-
Some (str_loc, `Method, get_class_field_kind_elements field_kind)
206+
| Typedtree.Tcf_val (str_loc, _, _, _field_kind, _) -> Some (str_loc, `Value)
207+
| Typedtree.Tcf_method (str_loc, _, _field_kind) -> Some (str_loc, `Method)
214208
| _ -> None
215209

216-
and get_class_field_kind_elements = function
217-
| Tcfk_virtual _ -> []
218-
| Tcfk_concrete (_, expr) -> get_expr_elements expr
219-
220-
and get_expr_elements expr =
221-
match expr.exp_desc with
222-
| Texp_let (_, vbs, expr) ->
223-
List.filter_map vbs ~f:(fun vb ->
224-
id_of_patt vb.vb_pat
225-
|> Option.map ~f:(fun ident ->
226-
let children = get_expr_elements vb.vb_expr in
227-
let deprecated = Type_utils.is_deprecated vb.vb_attributes in
228-
229-
mk ~children ~location:vb.vb_loc ~deprecated `Value None ident))
230-
@ get_expr_elements expr
231-
| Texp_object ({ cstr_fields; _ }, _) ->
232-
List.filter_map cstr_fields ~f:(fun field ->
233-
field.cf_desc |> get_class_field_desc_infos
234-
|> Option.map ~f:(fun (str_loc, outline_kind, children) ->
235-
let deprecated = Type_utils.is_deprecated field.cf_attributes in
236-
{ Query_protocol.outline_name = str_loc.Location.txt;
237-
outline_kind;
238-
outline_type = None;
239-
location = str_loc.Location.loc;
240-
children;
241-
deprecated
242-
}))
243-
| Texp_function (_, Tfunction_body expr) -> get_expr_elements expr
244-
| _ -> []
245-
246210
and get_mod_children node =
247211
List.concat_map (Lazy.force node.t_children) ~f:remove_mod_indir
248212

src/analysis/test.ml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
module Foo = struct
2+
type t = { foo : int; bar : int }
3+
4+
let foo = "hello"
5+
end
6+
7+
let _ =
8+
let foo = 10 in
9+
let bar = 10 in
10+
({ Foo.foo; bar } : Foo.t)

src/commands/query_json.ml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,7 @@ let rec json_of_outline outline =
326326
outline_kind;
327327
outline_type;
328328
location;
329+
selection;
329330
children;
330331
deprecated
331332
} =
@@ -337,7 +338,8 @@ let rec json_of_outline outline =
337338
| None -> `Null
338339
| Some typ -> `String typ );
339340
("children", `List (json_of_outline children));
340-
("deprecated", `Bool deprecated)
341+
("deprecated", `Bool deprecated);
342+
("selection", with_location selection [])
341343
]
342344
in
343345
List.map ~f:json_of_item outline

src/frontend/query_protocol.ml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,8 @@ and item =
9292
| `Method ];
9393
outline_type : string option;
9494
deprecated : bool;
95-
location : Location_aux.t;
95+
location : Location.t;
96+
selection : Location.t;
9697
children : outline
9798
}
9899

0 commit comments

Comments
 (0)