Skip to content

Commit 848fc44

Browse files
committed
Add --occurrences arg to compile-index
This adds the occurrence count to each element of the json index Signed-off-by: Paul-Elliot <peada@free.fr>
1 parent ecd7af3 commit 848fc44

File tree

8 files changed

+183
-63
lines changed

8 files changed

+183
-63
lines changed

src/odoc/bin/main.ml

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -524,7 +524,7 @@ module Indexing = struct
524524
| None, `Marshall -> Ok (Fs.File.of_string "index.odoc-index")
525525

526526
let index dst json warnings_options page_roots lib_roots inputs_in_file inputs
527-
=
527+
occurrences =
528528
let marshall = if json then `JSON else `Marshall in
529529
output_file ~dst marshall >>= fun output ->
530530
(if
@@ -534,8 +534,8 @@ module Indexing = struct
534534
then Error (`Msg "Paths given to all -P and -L options must be disjoint")
535535
else Ok ())
536536
>>= fun () ->
537-
Indexing.compile marshall ~output ~warnings_options ~lib_roots ~page_roots
538-
~inputs_in_file ~odocls:inputs
537+
Indexing.compile marshall ~output ~warnings_options ~occurrences ~lib_roots
538+
~page_roots ~inputs_in_file ~odocls:inputs
539539
let cmd =
540540
let dst =
541541
let doc =
@@ -546,6 +546,13 @@ module Indexing = struct
546546
Arg.(
547547
value & opt (some string) None & info ~docs ~docv:"PATH" ~doc [ "o" ])
548548
in
549+
let occurrences =
550+
let doc = "Occurrence file." in
551+
Arg.(
552+
value
553+
& opt (some convert_fpath) None
554+
& info ~docs ~docv:"PATH" ~doc [ "occurrences" ])
555+
in
549556
let inputs_in_file =
550557
let doc =
551558
"Input text file containing a line-separated list of paths to .odocl \
@@ -587,7 +594,7 @@ module Indexing = struct
587594
Term.(
588595
const handle_error
589596
$ (const index $ dst $ json $ warnings_options $ page_roots $ lib_roots
590-
$ inputs_in_file $ inputs))
597+
$ inputs_in_file $ inputs $ occurrences))
591598

592599
let info ~docs =
593600
let doc =

src/odoc/indexing.ml

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ let parse_input_files input =
4040
(Ok []) input
4141
>>= fun files -> Ok (List.concat files)
4242

43-
let compile_to_json ~output ~warnings_options files =
43+
let compile_to_json ~output ~warnings_options ~occurrences files =
4444
let output_channel =
4545
Fs.Directory.mkdir_p (Fs.File.dirname output);
4646
open_out_bin (Fs.File.to_string output)
@@ -57,7 +57,7 @@ let compile_to_json ~output ~warnings_options files =
5757
(fun acc file ->
5858
match
5959
handle_file
60-
~unit:(print Json_search.unit acc)
60+
~unit:(print (Json_search.unit ?occurrences) acc)
6161
~page:(print Json_search.page acc)
6262
~occ:(print Json_search.index acc)
6363
file
@@ -110,12 +110,22 @@ let compile_to_marshall ~output ~warnings_options sidebar files =
110110
result |> Error.handle_warnings ~warnings_options >>= fun () ->
111111
Ok (Odoc_file.save_index output (sidebar, final_index))
112112

113+
let read_occurrences file =
114+
let ic = open_in_bin file in
115+
let htbl : Odoc_occurrences.Table.t = Marshal.from_channel ic in
116+
htbl
117+
113118
open Odoc_model.Lang.Sidebar
114119

115-
let compile out_format ~output ~warnings_options ~lib_roots ~page_roots
116-
~inputs_in_file ~odocls =
120+
let compile out_format ~output ~warnings_options ~occurrences ~lib_roots
121+
~page_roots ~inputs_in_file ~odocls =
117122
parse_input_files inputs_in_file >>= fun files ->
118123
let files = List.rev_append odocls files in
124+
let occurrences =
125+
match occurrences with
126+
| None -> None
127+
| Some occurrences -> Some (read_occurrences (Fpath.to_string occurrences))
128+
in
119129
let resolver =
120130
Resolver.create ~important_digests:false ~directories:[]
121131
~roots:
@@ -168,5 +178,5 @@ let compile out_format ~output ~warnings_options ~lib_roots ~page_roots
168178
in
169179
let content = { pages; libraries } in
170180
match out_format with
171-
| `JSON -> compile_to_json ~output ~warnings_options files
181+
| `JSON -> compile_to_json ~output ~warnings_options ~occurrences files
172182
| `Marshall -> compile_to_marshall ~output ~warnings_options content files

src/odoc/indexing.mli

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ val compile :
1313
[ `JSON | `Marshall ] ->
1414
output:Fs.file ->
1515
warnings_options:Odoc_model.Error.warnings_options ->
16+
occurrences:Fs.file option ->
1617
lib_roots:(string * Fs.directory) list ->
1718
page_roots:(string * Fs.directory) list ->
1819
inputs_in_file:Fs.file list ->

src/search/json_index/dune

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
(library
22
(name odoc_json_index)
33
(public_name odoc.json_index)
4-
(libraries tyxml odoc_model odoc_search))
4+
(libraries tyxml odoc_model odoc_search odoc_occurrences))

src/search/json_index/json_search.ml

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ let of_doc (doc : Odoc_model.Comment.docs) =
8686
let txt = Text.of_doc doc in
8787
`String txt
8888

89-
let of_entry ({ Entry.id; doc; kind } as entry) html =
89+
let of_entry ({ Entry.id; doc; kind } as entry) html occurrences =
9090
let j_id = of_id id in
9191
let doc = of_doc doc in
9292
let kind =
@@ -167,11 +167,27 @@ let of_entry ({ Entry.id; doc; kind } as entry) html =
167167
("parent_type", `String (Text.of_type parent_type));
168168
]
169169
in
170+
let occurrences =
171+
match occurrences with
172+
| Some occ ->
173+
`Object
174+
[
175+
("direct", `Float (float_of_int occ.Odoc_occurrences.Table.direct));
176+
("indirect", `Float (float_of_int occ.indirect));
177+
]
178+
| None -> `Null
179+
in
170180
match Json_display.of_entry entry html with
171181
| Result.Ok display ->
172182
Result.Ok
173183
(`Object
174-
[ ("id", j_id); ("doc", doc); ("kind", kind); ("display", display) ])
184+
[
185+
("id", j_id);
186+
("doc", doc);
187+
("kind", kind);
188+
("display", display);
189+
("occurrences", occurrences);
190+
])
175191
| Error _ as e -> e
176192

177193
let output_json ppf first entries =
@@ -180,8 +196,8 @@ let output_json ppf first entries =
180196
Format.fprintf ppf "%s\n" str
181197
in
182198
List.fold_left
183-
(fun first (entry, html) ->
184-
let json = of_entry entry html in
199+
(fun first (entry, html, occurrences) ->
200+
let json = of_entry entry html occurrences in
185201
if not first then Format.fprintf ppf ",";
186202
match json with
187203
| Ok json ->
@@ -192,11 +208,20 @@ let output_json ppf first entries =
192208
true)
193209
first entries
194210

195-
let unit ppf u =
211+
let unit ?occurrences ppf u =
212+
let get_occ id =
213+
match occurrences with
214+
| None -> None
215+
| Some occurrences -> Odoc_occurrences.Table.get occurrences id
216+
in
196217
let f first i =
197218
let entries = Entry.entries_of_item i in
198219
let entries =
199-
List.map (fun entry -> (entry, Html.of_entry entry)) entries
220+
List.map
221+
(fun entry ->
222+
let occ = get_occ entry.Entry.id in
223+
(entry, Html.of_entry entry, occ))
224+
entries
200225
in
201226
let first = output_json ppf first entries in
202227
first
@@ -208,7 +233,7 @@ let page ppf (page : Odoc_model.Lang.Page.t) =
208233
let f first i =
209234
let entries = Entry.entries_of_item i in
210235
let entries =
211-
List.map (fun entry -> (entry, Html.of_entry entry)) entries
236+
List.map (fun entry -> (entry, Html.of_entry entry, None)) entries
212237
in
213238
output_json ppf first entries
214239
in
@@ -219,7 +244,7 @@ let index ppf (index : Entry.t Odoc_model.Paths.Identifier.Hashtbl.Any.t) =
219244
let _first =
220245
Odoc_model.Paths.Identifier.Hashtbl.Any.fold
221246
(fun _id entry first ->
222-
let entry = (entry, Html.of_entry entry) in
247+
let entry = (entry, Html.of_entry entry, None) in
223248
output_json ppf first [ entry ])
224249
index true
225250
in

src/search/json_index/json_search.mli

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
(** This module generates json intended to be consumed by search engines. *)
22

3-
val unit : Format.formatter -> Odoc_model.Lang.Compilation_unit.t -> unit
3+
val unit :
4+
?occurrences:Odoc_occurrences.Table.t ->
5+
Format.formatter ->
6+
Odoc_model.Lang.Compilation_unit.t ->
7+
unit
48
val page : Format.formatter -> Odoc_model.Lang.Page.t -> unit
59
val index :
610
Format.formatter ->

test/occurrences/double_wrapped.t/run.t

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,3 +144,76 @@ We can also include hidden ids:
144144
Main__A was used directly 1 times and indirectly 0 times
145145
Main__B was used directly 1 times and indirectly 0 times
146146
Main__C was used directly 1 times and indirectly 0 times
147+
148+
We can use the generated table when generating the json output:
149+
150+
$ odoc link -I . main.odoc
151+
152+
$ odoc compile-index --json -o index.json --occurrences occurrences-all.odoc main.odocl
153+
154+
$ cat index.json | jq sort | jq '.[]' -c
155+
{"id":[{"kind":"Root","name":"Main"}],"doc":"Handwritten top-level module","kind":{"kind":"Module"},"display":{"url":"Main/index.html","html":"<code class=\"entry-kind\">mod</code><code class=\"entry-title\"><span class=\"entry-name\">Main</span></code><div class=\"entry-comment\"><div><p>Handwritten top-level module</p></div></div>"},"occurrences":{"direct":0,"indirect":11}}
156+
{"id":[{"kind":"Root","name":"Main"},{"kind":"Module","name":"A"}],"doc":"","kind":{"kind":"Module"},"display":{"url":"Main/index.html#module-A","html":"<code class=\"entry-kind\">mod</code><code class=\"entry-title\"><span class=\"prefix-name\">Main.</span><span class=\"entry-name\">A</span></code><div class=\"entry-comment\"><div></div></div>"},"occurrences":{"direct":4,"indirect":6}}
157+
{"id":[{"kind":"Root","name":"Main"},{"kind":"Module","name":"B"}],"doc":"","kind":{"kind":"Module"},"display":{"url":"Main/index.html#module-B","html":"<code class=\"entry-kind\">mod</code><code class=\"entry-title\"><span class=\"prefix-name\">Main.</span><span class=\"entry-name\">B</span></code><div class=\"entry-comment\"><div></div></div>"},"occurrences":{"direct":1,"indirect":0}}
158+
{"id":[{"kind":"Root","name":"Main"},{"kind":"Module","name":"B"},{"kind":"Module","name":"M"}],"doc":"","kind":{"kind":"Module"},"display":{"url":"Main/B/index.html#module-M","html":"<code class=\"entry-kind\">mod</code><code class=\"entry-title\"><span class=\"prefix-name\">Main.B.</span><span class=\"entry-name\">M</span></code><div class=\"entry-comment\"><div></div></div>"},"occurrences":null}
159+
{"id":[{"kind":"Root","name":"Main"},{"kind":"Module","name":"B"},{"kind":"Module","name":"Y"}],"doc":"","kind":{"kind":"Module"},"display":{"url":"Main/B/index.html#module-Y","html":"<code class=\"entry-kind\">mod</code><code class=\"entry-title\"><span class=\"prefix-name\">Main.B.</span><span class=\"entry-name\">Y</span></code><div class=\"entry-comment\"><div></div></div>"},"occurrences":null}
160+
{"id":[{"kind":"Root","name":"Main"},{"kind":"Module","name":"B"},{"kind":"Module","name":"Z"}],"doc":"","kind":{"kind":"Module"},"display":{"url":"Main/B/index.html#module-Z","html":"<code class=\"entry-kind\">mod</code><code class=\"entry-title\"><span class=\"prefix-name\">Main.B.</span><span class=\"entry-name\">Z</span></code><div class=\"entry-comment\"><div></div></div>"},"occurrences":null}
161+
{"id":[{"kind":"Root","name":"Main"},{"kind":"Module","name":"B"},{"kind":"Module","name":"Z"},{"kind":"Module","name":"Y"}],"doc":"","kind":{"kind":"Module"},"display":{"url":"Main/B/Z/index.html#module-Y","html":"<code class=\"entry-kind\">mod</code><code class=\"entry-title\"><span class=\"prefix-name\">Main.B.Z.</span><span class=\"entry-name\">Y</span></code><div class=\"entry-comment\"><div></div></div>"},"occurrences":null}
162+
{"id":[{"kind":"Root","name":"Main"},{"kind":"Module","name":"A"},{"kind":"ModuleType","name":"M"}],"doc":"","kind":{"kind":"ModuleType"},"display":{"url":"Main/A/index.html#module-type-M","html":"<code class=\"entry-kind\">sig</code><code class=\"entry-title\"><span class=\"prefix-name\">Main.A.</span><span class=\"entry-name\">M</span></code><div class=\"entry-comment\"><div></div></div>"},"occurrences":{"direct":2,"indirect":0}}
163+
{"id":[{"kind":"Root","name":"Main"},{"kind":"Module","name":"B"},{"kind":"ModuleType","name":"Y"}],"doc":"","kind":{"kind":"ModuleType"},"display":{"url":"Main/B/index.html#module-type-Y","html":"<code class=\"entry-kind\">sig</code><code class=\"entry-title\"><span class=\"prefix-name\">Main.B.</span><span class=\"entry-name\">Y</span></code><div class=\"entry-comment\"><div></div></div>"},"occurrences":null}
164+
{"id":[{"kind":"Root","name":"Main"},{"kind":"Module","name":"A"},{"kind":"Type","name":"t"}],"doc":"","kind":{"kind":"TypeDecl","private":false,"manifest":"string","constraints":[]},"display":{"url":"Main/A/index.html#type-t","html":"<code class=\"entry-kind\">type</code><code class=\"entry-title\"><span class=\"prefix-name\">Main.A.</span><span class=\"entry-name\">t</span><code class=\"entry-rhs\"> = string</code></code><div class=\"entry-comment\"><div></div></div>"},"occurrences":{"direct":1,"indirect":0}}
165+
{"id":[{"kind":"Root","name":"Main"},{"kind":"Module","name":"A"},{"kind":"Value","name":"(||>)"}],"doc":"","kind":{"kind":"Value","type":"int -> int -> int"},"display":{"url":"Main/A/index.html#val-(||>)","html":"<code class=\"entry-kind\">val</code><code class=\"entry-title\"><span class=\"prefix-name\">Main.A.</span><span class=\"entry-name\">(||&gt;)</span><code class=\"entry-rhs\"> : int -&gt; int -&gt; int</code></code><div class=\"entry-comment\"><div></div></div>"},"occurrences":{"direct":1,"indirect":0}}
166+
{"id":[{"kind":"Root","name":"Main"},{"kind":"Module","name":"A"},{"kind":"Value","name":"x"}],"doc":"","kind":{"kind":"Value","type":"int"},"display":{"url":"Main/A/index.html#val-x","html":"<code class=\"entry-kind\">val</code><code class=\"entry-title\"><span class=\"prefix-name\">Main.A.</span><span class=\"entry-name\">x</span><code class=\"entry-rhs\"> : int</code></code><div class=\"entry-comment\"><div></div></div>"},"occurrences":{"direct":2,"indirect":0}}
167+
{"id":[{"kind":"Root","name":"Main"},{"kind":"Module","name":"B"},{"kind":"Value","name":"y"}],"doc":"","kind":{"kind":"Value","type":"int"},"display":{"url":"Main/B/index.html#val-y","html":"<code class=\"entry-kind\">val</code><code class=\"entry-title\"><span class=\"prefix-name\">Main.B.</span><span class=\"entry-name\">y</span><code class=\"entry-rhs\"> : int</code></code><div class=\"entry-comment\"><div></div></div>"},"occurrences":null}
168+
{"id":[{"kind":"Root","name":"Main"},{"kind":"Module","name":"B"},{"kind":"Module","name":"Z"},{"kind":"Value","name":"y"}],"doc":"","kind":{"kind":"Value","type":"int"},"display":{"url":"Main/B/Z/index.html#val-y","html":"<code class=\"entry-kind\">val</code><code class=\"entry-title\"><span class=\"prefix-name\">Main.B.Z.</span><span class=\"entry-name\">y</span><code class=\"entry-rhs\"> : int</code></code><div class=\"entry-comment\"><div></div></div>"},"occurrences":null}
169+
170+
$ cat index.json | jq sort | head -n 33
171+
[
172+
{
173+
"id": [
174+
{
175+
"kind": "Root",
176+
"name": "Main"
177+
}
178+
],
179+
"doc": "Handwritten top-level module",
180+
"kind": {
181+
"kind": "Module"
182+
},
183+
"display": {
184+
"url": "Main/index.html",
185+
"html": "<code class=\"entry-kind\">mod</code><code class=\"entry-title\"><span class=\"entry-name\">Main</span></code><div class=\"entry-comment\"><div><p>Handwritten top-level module</p></div></div>"
186+
},
187+
"occurrences": {
188+
"direct": 0,
189+
"indirect": 11
190+
}
191+
},
192+
{
193+
"id": [
194+
{
195+
"kind": "Root",
196+
"name": "Main"
197+
},
198+
{
199+
"kind": "Module",
200+
"name": "A"
201+
}
202+
],
203+
"doc": "",
204+
205+
$ cat index.json | jq -r '.[] | "\(.id | map("\(.kind)-\(.name)") | join(".")), direct: \(.occurrences.direct), indirect: \(.occurrences.indirect)"' | sort
206+
Root-Main, direct: 0, indirect: 11
207+
Root-Main.Module-A, direct: 4, indirect: 6
208+
Root-Main.Module-A.ModuleType-M, direct: 2, indirect: 0
209+
Root-Main.Module-A.Type-t, direct: 1, indirect: 0
210+
Root-Main.Module-A.Value-(||>), direct: 1, indirect: 0
211+
Root-Main.Module-A.Value-x, direct: 2, indirect: 0
212+
Root-Main.Module-B, direct: 1, indirect: 0
213+
Root-Main.Module-B.Module-M, direct: null, indirect: null
214+
Root-Main.Module-B.Module-Y, direct: null, indirect: null
215+
Root-Main.Module-B.Module-Z, direct: null, indirect: null
216+
Root-Main.Module-B.Module-Z.Module-Y, direct: null, indirect: null
217+
Root-Main.Module-B.Module-Z.Value-y, direct: null, indirect: null
218+
Root-Main.Module-B.ModuleType-Y, direct: null, indirect: null
219+
Root-Main.Module-B.Value-y, direct: null, indirect: null

0 commit comments

Comments
 (0)