Skip to content

Commit e24b8a2

Browse files
panglesdjonludlam
authored andcommitted
Source code: Avoid having two anchors at an identical location
Signed-off-by: Paul-Elliot <[email protected]>
1 parent 53aad53 commit e24b8a2

File tree

3 files changed

+71
-60
lines changed

3 files changed

+71
-60
lines changed

src/loader/implementation.ml

Lines changed: 66 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -132,39 +132,54 @@ module Env = struct
132132
env
133133
end
134134

135-
let postprocess_poses source_id poses uid_to_id uid_to_loc :
135+
module LocHashtbl = Hashtbl.Make (struct
136+
type t = Location.t
137+
let equal l1 l2 = l1 = l2
138+
let hash = Hashtbl.hash
139+
end)
140+
141+
module IdentHashtbl = Hashtbl.Make (struct
142+
type t = Ident.t
143+
let equal l1 l2 = l1 = l2
144+
let hash = Hashtbl.hash
145+
end)
146+
147+
(* generate a [loc_to_id] and an [ident_to_id] map *)
148+
let local_maps source_id poses =
149+
let loc_tbl = LocHashtbl.create 10 and ident_to_id = IdentHashtbl.create 10 in
150+
List.iter
151+
(function
152+
| Typedtree_traverse.Analysis.Definition id, loc ->
153+
let name =
154+
Odoc_model.Names.LocalName.make_std
155+
(Printf.sprintf "local_%s_%d" (Ident.name id) (counter ()))
156+
in
157+
let identifier =
158+
Odoc_model.Paths.Identifier.Mk.source_location_int (source_id, name)
159+
in
160+
IdentHashtbl.add ident_to_id id identifier;
161+
LocHashtbl.add loc_tbl loc identifier
162+
| _ -> ())
163+
poses;
164+
(loc_tbl, ident_to_id)
165+
166+
let postprocess_poses poses ident_to_id loc_to_id uid_to_id uid_to_loc :
136167
Odoc_model.Lang.Source_info.infos =
137-
let local_def_anchors =
138-
List.filter_map
139-
(function
140-
| Typedtree_traverse.Analysis.Definition id, _ ->
141-
let name =
142-
Odoc_model.Names.LocalName.make_std
143-
(Printf.sprintf "local_%s_%d" (Ident.name id) (counter ()))
144-
in
145-
let identifier =
146-
Odoc_model.Paths.Identifier.Mk.source_location_int
147-
(source_id, name)
148-
in
149-
Some (id, identifier)
150-
| _ -> None)
151-
poses
152-
in
153168
let poses =
154169
List.filter_map
155170
(function
156171
| Typedtree_traverse.Analysis.Definition id, loc ->
157172
Some
158173
( Odoc_model.Lang.Source_info.Definition
159-
(List.assoc id local_def_anchors),
160-
loc )
174+
(IdentHashtbl.find ident_to_id id),
175+
pos_of_loc loc )
161176
| Value (LocalValue uniq), loc -> (
162-
match List.assoc_opt uniq local_def_anchors with
163-
| Some anchor -> Some (Value anchor, loc)
177+
match IdentHashtbl.find_opt ident_to_id uniq with
178+
| Some anchor -> Some (Value anchor, pos_of_loc loc)
164179
| None -> None)
165180
| Value (DefJmp x), loc -> (
166181
match Shape.Uid.Map.find_opt x uid_to_id with
167-
| Some id -> Some (Value id, loc)
182+
| Some id -> Some (Value id, pos_of_loc loc)
168183
| None -> None))
169184
poses
170185
in
@@ -173,7 +188,7 @@ let postprocess_poses source_id poses uid_to_id uid_to_loc :
173188
(fun uid id acc ->
174189
let loc_opt = Shape.Uid.Tbl.find_opt uid_to_loc uid in
175190
match loc_opt with
176-
| Some loc ->
191+
| Some loc when not (LocHashtbl.mem loc_to_id loc) ->
177192
(Odoc_model.Lang.Source_info.Definition id, pos_of_loc loc) :: acc
178193
| _ -> acc)
179194
uid_to_id []
@@ -259,60 +274,58 @@ let anchor_of_identifier id =
259274

260275
(** Returns an environment (containing a [loc] to [id] map) and an [uid] to [id]
261276
maps. *)
262-
let id_maps_of_cmt (source_id : Odoc_model.Paths.Identifier.SourcePage.t)
263-
(id : Odoc_model.Paths.Identifier.RootModule.t)
264-
(structure : Typedtree.structure)
265-
(uid_to_loc : Warnings.loc Types.Uid.Tbl.t) =
266-
let env = Env.of_structure id structure in
277+
let id_map_of_cmt env (source_id : Odoc_model.Paths.Identifier.SourcePage.t)
278+
(uid_to_loc : Warnings.loc Types.Uid.Tbl.t) local_loc_to_id =
267279
let uid_to_loc_map = Shape.Uid.Tbl.to_map uid_to_loc in
280+
let mk_id name =
281+
Some
282+
(Odoc_model.Paths.Identifier.Mk.source_location (source_id, name)
283+
:> Odoc_model.Paths.Identifier.SourceLocation.t)
284+
in
268285
let uid_to_id : Odoc_model.Paths.Identifier.SourceLocation.t Shape.Uid.Map.t =
269286
Shape.Uid.Map.filter_map
270287
(fun uid loc ->
271288
if loc.Location.loc_ghost then None
272289
else
273290
let identifier = Ident_env.identifier_of_loc env loc in
274-
let anchor =
275-
match identifier with
276-
| Some x ->
277-
Some
278-
(Odoc_model.Names.DefName.make_std (anchor_of_identifier x))
279-
| None -> (
280-
match uid with
281-
| Compilation_unit _ -> None
282-
| Item _ ->
283-
let name =
284-
Odoc_model.Names.DefName.make_std
285-
(Printf.sprintf "def_%d" (counter ()))
286-
in
287-
Some name
288-
| _ -> None)
289-
in
290-
match anchor with
291-
| Some a ->
292-
Some
293-
(Odoc_model.Paths.Identifier.Mk.source_location (source_id, a)
294-
:> Odoc_model.Paths.Identifier.SourceLocation.t)
295-
| None -> None)
291+
match identifier with
292+
| Some x ->
293+
mk_id (Odoc_model.Names.DefName.make_std (anchor_of_identifier x))
294+
| None -> (
295+
match uid with
296+
| Compilation_unit _ -> None
297+
| Item _ -> (
298+
match LocHashtbl.find_opt local_loc_to_id loc with
299+
| Some anchor -> Some anchor
300+
| None ->
301+
let name =
302+
Odoc_model.Names.DefName.make_std
303+
(Printf.sprintf "def_%d" (counter ()))
304+
in
305+
mk_id name)
306+
| _ -> None))
296307
uid_to_loc_map
297308
in
298-
(uid_to_id, env)
309+
uid_to_id
299310

300311
let read_cmt_infos source_id_opt id cmt_info =
301312
match Odoc_model.Compat.shape_of_cmt_infos cmt_info with
302313
| Some shape -> (
303314
let uid_to_loc = cmt_info.cmt_uid_to_loc in
304315
match (source_id_opt, cmt_info.cmt_annots) with
305316
| Some source_id, Implementation impl ->
306-
let map, env = id_maps_of_cmt source_id id impl uid_to_loc in
317+
let env = Env.of_structure id impl in
307318
let occ_infos =
308319
Typedtree_traverse.of_cmt env uid_to_loc impl |> List.rev
309320
(* Information are accumulated in a list. We need to have the
310321
first info first in the list, to assign anchors with increasing
311322
numbers, so that adding some content at the end of a file does
312323
not modify the anchors for existing anchors. *)
313324
in
325+
let loc_to_id, ident_to_id = local_maps source_id occ_infos in
326+
let map = id_map_of_cmt env source_id uid_to_loc loc_to_id in
314327
let source_infos =
315-
postprocess_poses source_id occ_infos map uid_to_loc
328+
postprocess_poses occ_infos ident_to_id loc_to_id map uid_to_loc
316329
in
317330
( Some (shape, map),
318331
Some

src/loader/typedtree_traverse.ml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
#if OCAML_VERSION >= (4, 14, 0)
22

3-
let pos_of_loc loc = (loc.Location.loc_start.pos_cnum, loc.loc_end.pos_cnum)
4-
53
module Analysis = struct
64
type value_implementation = LocalValue of Ident.t | DefJmp of Shape.Uid.t
75

@@ -23,14 +21,14 @@ module Analysis = struct
2321
in
2422
match implementation with
2523
| None -> ()
26-
| Some impl -> poses := (Value impl, pos_of_loc exp_loc) :: !poses)
24+
| Some impl -> poses := (Value impl, exp_loc) :: !poses)
2725
| _ -> ()
2826

2927
let pat env (type a) poses : a Typedtree.general_pattern -> unit = function
3028
| { Typedtree.pat_desc; pat_loc; _ } when not pat_loc.loc_ghost ->
3129
let maybe_localvalue id loc =
3230
match Ident_env.identifier_of_loc env loc with
33-
| None -> Some (Definition id, pos_of_loc loc)
31+
| None -> Some (Definition id, loc)
3432
| Some _ -> None
3533
in
3634
let () =

test/sources/source.t/run.t

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -279,9 +279,9 @@ Ids generated in the source code:
279279
id="val-{x}2"
280280
id="val-y"
281281
id="val-z"
282-
id="local_a_2"
282+
id="local_a_1"
283283
id="val-z'"
284-
id="local_a_3"
284+
id="local_a_2"
285285
id="module-A"
286286
id="module-B"
287287
id="module-type-T"
@@ -303,7 +303,7 @@ Ids generated in the source code:
303303
id="module-F.argument-1-M.module-A"
304304
id="module-F.module-B"
305305
id="module-FM"
306-
id="def_1"
306+
id="def_3"
307307
id="module-FF"
308308
id="module-FF2"
309309
id="module-FF2.argument-1-A.module-E"

0 commit comments

Comments
 (0)