Skip to content

Commit 1b18802

Browse files
panglesdjonludlam
authored andcommitted
Render source code: tidy up info extraction
Signed-off-by: Paul-Elliot <[email protected]>
1 parent e24b8a2 commit 1b18802

File tree

4 files changed

+90
-79
lines changed

4 files changed

+90
-79
lines changed

src/loader/ident_env.cppo.ml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -605,6 +605,9 @@ let add_items : Id.Signature.t -> item list -> t -> t = fun parent items env ->
605605
let identifier_of_loc : t -> Location.t -> Odoc_model.Paths.Identifier.t option = fun env loc ->
606606
try Some (LocHashtbl.find env.loc_to_ident loc) with Not_found -> None
607607

608+
let iter_located_identifier : t -> (Location.t -> Odoc_model.Paths.Identifier.t -> unit) -> unit = fun env f ->
609+
LocHashtbl.iter f env.loc_to_ident
610+
608611
let add_signature_tree_items : Paths.Identifier.Signature.t -> Typedtree.signature -> t -> t =
609612
fun parent sg env ->
610613
let items = extract_signature_tree_items false sg.sig_items |> flatten_includes in

src/loader/ident_env.cppo.mli

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,10 @@ module Fragment : sig
7777
val read_type : Longident.t -> Paths.Fragment.Type.t
7878
end
7979

80-
val identifier_of_loc : t -> Location.t -> Odoc_model.Paths.Identifier.t option
80+
val identifier_of_loc : t -> Location.t -> Paths.Identifier.t option
8181
(** Each generated id has its location stored. This allows to get back the id
8282
knowing only the location. This is used to generate links to source from the
8383
resolution of a shape. *)
84+
85+
val iter_located_identifier : t -> (Location.t -> Paths.Identifier.t -> unit) -> unit
86+
(** Iter on all stored pair [location]-[identifier]. *)

src/loader/implementation.ml

Lines changed: 79 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -144,10 +144,11 @@ module IdentHashtbl = Hashtbl.Make (struct
144144
let hash = Hashtbl.hash
145145
end)
146146

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
147+
(* populate a [loc_to_id] and an [ident_to_id] map with local informations. Also
148+
removes the definitions from the list, since their information has been taken
149+
into account *)
150+
let process_local_defs source_id poses loc_tbl ident_to_id =
151+
List.filter_map
151152
(function
152153
| Typedtree_traverse.Analysis.Definition id, loc ->
153154
let name =
@@ -158,43 +159,13 @@ let local_maps source_id poses =
158159
Odoc_model.Paths.Identifier.Mk.source_location_int (source_id, name)
159160
in
160161
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 :
167-
Odoc_model.Lang.Source_info.infos =
168-
let poses =
169-
List.filter_map
170-
(function
171-
| Typedtree_traverse.Analysis.Definition id, loc ->
172-
Some
173-
( Odoc_model.Lang.Source_info.Definition
174-
(IdentHashtbl.find ident_to_id id),
175-
pos_of_loc loc )
176-
| Value (LocalValue uniq), loc -> (
177-
match IdentHashtbl.find_opt ident_to_id uniq with
178-
| Some anchor -> Some (Value anchor, pos_of_loc loc)
179-
| None -> None)
180-
| Value (DefJmp x), loc -> (
181-
match Shape.Uid.Map.find_opt x uid_to_id with
182-
| Some id -> Some (Value id, pos_of_loc loc)
183-
| None -> None))
184-
poses
185-
in
186-
let defs =
187-
Shape.Uid.Map.fold
188-
(fun uid id acc ->
189-
let loc_opt = Shape.Uid.Tbl.find_opt uid_to_loc uid in
190-
match loc_opt with
191-
| Some loc when not (LocHashtbl.mem loc_to_id loc) ->
192-
(Odoc_model.Lang.Source_info.Definition id, pos_of_loc loc) :: acc
193-
| _ -> acc)
194-
uid_to_id []
195-
in
196-
defs @ poses
162+
LocHashtbl.add loc_tbl loc identifier;
163+
None
164+
| x -> Some x)
165+
poses
197166

167+
(* In order to turn an identifier into a source identifier, we need to generate
168+
a unique anchor for any identifier. *)
198169
let anchor_of_identifier id =
199170
let open Odoc_document.Url in
200171
let open Odoc_model.Paths in
@@ -272,41 +243,65 @@ let anchor_of_identifier id =
272243
in
273244
anchor_of_identifier [] id |> String.concat "."
274245

275-
(** Returns an environment (containing a [loc] to [id] map) and an [uid] to [id]
276-
maps. *)
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 =
279-
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)
246+
(* Adds the global defs from the odoc environment to [loc_to_id] table *)
247+
let process_global_defs env source_id loc_to_id =
248+
let mk_src_id id =
249+
let name = Odoc_model.Names.DefName.make_std (anchor_of_identifier id) in
250+
(Odoc_model.Paths.Identifier.Mk.source_location (source_id, name)
251+
:> Odoc_model.Paths.Identifier.SourceLocation.t)
284252
in
285-
let uid_to_id : Odoc_model.Paths.Identifier.SourceLocation.t Shape.Uid.Map.t =
286-
Shape.Uid.Map.filter_map
287-
(fun uid loc ->
288-
if loc.Location.loc_ghost then None
289-
else
290-
let identifier = Ident_env.identifier_of_loc env loc in
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))
307-
uid_to_loc_map
253+
Ident_env.iter_located_identifier env @@ fun loc id ->
254+
LocHashtbl.add loc_to_id loc (mk_src_id id)
255+
256+
(* The [uid_to_id] is useful as when resolving a shape, we get the uid. *)
257+
let build_uid_to_id source_id uid_to_loc loc_to_id =
258+
let uid_to_loc_map = Shape.Uid.Tbl.to_map uid_to_loc in
259+
let mk_src_id () =
260+
let name =
261+
Odoc_model.Names.DefName.make_std (Printf.sprintf "def_%d" (counter ()))
262+
in
263+
(Odoc_model.Paths.Identifier.Mk.source_location (source_id, name)
264+
:> Odoc_model.Paths.Identifier.SourceLocation.t)
308265
in
309-
uid_to_id
266+
Shape.Uid.Map.filter_map
267+
(fun uid loc ->
268+
if loc.Location.loc_ghost then None
269+
else
270+
match LocHashtbl.find_opt loc_to_id loc with
271+
| Some id -> Some id
272+
| None -> (
273+
(* In case there is no entry for the location of the uid, we add one. *)
274+
match uid with
275+
| Item _ ->
276+
let id = mk_src_id () in
277+
LocHashtbl.add loc_to_id loc id;
278+
Some id
279+
| Compilation_unit _ -> None
280+
| _ -> None))
281+
uid_to_loc_map
282+
283+
(* Turns [Typedtree_traverse] occurrence information into proper source infos *)
284+
let process_occurrences poses uid_to_id ident_to_id =
285+
List.filter_map
286+
(function
287+
| Typedtree_traverse.Analysis.Value (LocalValue uniq), loc -> (
288+
match IdentHashtbl.find_opt ident_to_id uniq with
289+
| Some anchor ->
290+
Some (Odoc_model.Lang.Source_info.Value anchor, pos_of_loc loc)
291+
| None -> None)
292+
| Value (DefJmp x), loc -> (
293+
match Shape.Uid.Map.find_opt x uid_to_id with
294+
| Some id -> Some (Value id, pos_of_loc loc)
295+
| None -> None)
296+
| Definition _, _ -> None)
297+
poses
298+
299+
(* Add definition source info from the [loc_to_id] table *)
300+
let add_definitions occurrences loc_to_id =
301+
LocHashtbl.fold
302+
(fun loc id acc ->
303+
(Odoc_model.Lang.Source_info.Definition id, pos_of_loc loc) :: acc)
304+
loc_to_id occurrences
310305

311306
let read_cmt_infos source_id_opt id cmt_info =
312307
match Odoc_model.Compat.shape_of_cmt_infos cmt_info with
@@ -322,12 +317,18 @@ let read_cmt_infos source_id_opt id cmt_info =
322317
numbers, so that adding some content at the end of a file does
323318
not modify the anchors for existing anchors. *)
324319
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
327-
let source_infos =
328-
postprocess_poses occ_infos ident_to_id loc_to_id map uid_to_loc
320+
let loc_to_id = LocHashtbl.create 10
321+
and ident_to_id = IdentHashtbl.create 10 in
322+
let occurrences =
323+
process_local_defs source_id occ_infos loc_to_id ident_to_id
324+
in
325+
let () = process_global_defs env source_id loc_to_id in
326+
let uid_to_id = build_uid_to_id source_id uid_to_loc loc_to_id in
327+
let occurrences =
328+
process_occurrences occurrences uid_to_id ident_to_id
329329
in
330-
( Some (shape, map),
330+
let source_infos = add_definitions occurrences loc_to_id in
331+
( Some (shape, uid_to_id),
331332
Some
332333
{
333334
Odoc_model.Lang.Source_info.id = source_id;

test/sources/source.t/run.t

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,9 +272,13 @@ Ids generated in the source code:
272272
id="L61"
273273
id="type-t"
274274
id="type-truc"
275+
id="type-truc.constructor-A"
276+
id="type-truc.constructor-B"
275277
id="val-xazaz"
276278
id="module-Yoyo"
277279
id="module-Yoyo.type-bli"
280+
id="module-Yoyo.type-bli.constructor-Aa"
281+
id="module-Yoyo.type-bli.constructor-Bb"
278282
id="val-segr"
279283
id="val-{x}2"
280284
id="val-y"

0 commit comments

Comments
 (0)