1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
open StdLabels
open Or_error
module Odoc_compile = Compile
module Compile = struct
type t = { unit_name : string; digest : Digest.t }
let name t = t.unit_name
let digest t = t.digest
let compare t1 t2 =
match String.compare (name t1) (name t2) with
| 0 -> Digest.compare (digest t1) (digest t2)
| n -> n
end
module Compile_set = Set.Make (Compile)
let add_dep acc = function
| _, None -> acc
| unit_name, Some digest -> Compile_set.add { Compile.unit_name; digest } acc
let for_compile_step_cmt acc file =
let cmt_infos = Cmt_format.read_cmt (Fs.File.to_string file) in
List.fold_left ~f:add_dep ~init:acc cmt_infos.Cmt_format.cmt_imports
let for_compile_step_cmi_or_cmti acc file =
let cmi_infos = Cmi_format.read_cmi (Fs.File.to_string file) in
List.fold_left ~f:add_dep ~init:acc cmi_infos.Cmi_format.cmi_crcs
let for_compile_step files =
let set =
List.fold_left
~f:(fun acc file ->
if Fs.File.has_ext "cmt" file then for_compile_step_cmt acc file
else for_compile_step_cmi_or_cmti acc file)
~init:Compile_set.empty files
in
Compile_set.fold (fun a b -> a :: b) set []
module Hash_set : sig
type t
val create : unit -> t
val add : t -> Odoc_model.Root.t -> unit
val elements : t -> Odoc_model.Root.t list
end = struct
type t = unit Odoc_model.Root.Hash_table.t
let add t elt =
if Odoc_model.Root.Hash_table.mem t elt then ()
else Odoc_model.Root.Hash_table.add t elt ()
let create () = Odoc_model.Root.Hash_table.create 42
let elements t =
Odoc_model.Root.Hash_table.fold (fun s () acc -> s :: acc) t []
end
let deps_of_imports ~deps imports =
List.iter imports ~f:(fun import ->
match import with
| Odoc_model.Lang.Compilation_unit.Import.Unresolved _ -> ()
| Odoc_model.Lang.Compilation_unit.Import.Resolved (root, _) ->
Hash_set.add deps root);
Ok ()
let deps_of_odoc_file ~deps input =
Odoc_file.load input >>= fun unit ->
match unit.content with
| Page_content _ | Asset_content _ ->
Ok ()
| Impl_content impl ->
deps_of_imports ~deps impl.Odoc_model.Lang.Implementation.imports
| Unit_content unit ->
deps_of_imports ~deps unit.Odoc_model.Lang.Compilation_unit.imports
let for_rendering_step pkg_dir =
let deps = Hash_set.create () in
let add_deps () file = deps_of_odoc_file ~deps file in
Fs.Directory.fold_files_rec_result ~ext:".odoc" add_deps () pkg_dir
>>= fun () -> Ok (Hash_set.elements deps)