Merge pull request #864 from rgrinberg/doc-private
Refactor odoc generation and fix the private doc alias
This commit is contained in:
commit
79b8caf4d2
|
@ -66,6 +66,9 @@ next
|
||||||
whether a multi valued variable is allowed is determined by the quoting and
|
whether a multi valued variable is allowed is determined by the quoting and
|
||||||
substitution context it appears in. (#849, fix #701, @rgrinberg)
|
substitution context it appears in. (#849, fix #701, @rgrinberg)
|
||||||
|
|
||||||
|
- Fix documentation generation for private libraries. (#864, fix #856,
|
||||||
|
@rgrinberg)
|
||||||
|
|
||||||
1.0+beta20 (10/04/2018)
|
1.0+beta20 (10/04/2018)
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
|
|
136
src/odoc.ml
136
src/odoc.ml
|
@ -22,10 +22,20 @@ type target =
|
||||||
| Lib of Lib.t
|
| Lib of Lib.t
|
||||||
| Pkg of Package.Name.t
|
| Pkg of Package.Name.t
|
||||||
|
|
||||||
|
type source = Module | Mld
|
||||||
|
|
||||||
|
type odoc =
|
||||||
|
{ odoc_input: Path.t
|
||||||
|
; html_dir: Path.t
|
||||||
|
; html_file: Path.t
|
||||||
|
; source: source
|
||||||
|
}
|
||||||
|
|
||||||
module Gen (S : sig val sctx : SC.t end) = struct
|
module Gen (S : sig val sctx : SC.t end) = struct
|
||||||
open S
|
open S
|
||||||
|
|
||||||
let context = SC.context sctx
|
let context = SC.context sctx
|
||||||
|
let stanzas = SC.stanzas sctx
|
||||||
|
|
||||||
module Paths = struct
|
module Paths = struct
|
||||||
let root = context.Context.build_dir ++ "_doc"
|
let root = context.Context.build_dir ++ "_doc"
|
||||||
|
@ -138,14 +148,6 @@ module Gen (S : sig val sctx : SC.t end) = struct
|
||||||
]);
|
]);
|
||||||
odoc_file
|
odoc_file
|
||||||
|
|
||||||
type odoc =
|
|
||||||
{ odoc_input: Path.t
|
|
||||||
; html_dir: Path.t
|
|
||||||
; html_file: Path.t
|
|
||||||
; html_alias: Build_system.Alias.t
|
|
||||||
; typ: [`Module | `Mld]
|
|
||||||
}
|
|
||||||
|
|
||||||
let odoc_include_flags requires =
|
let odoc_include_flags requires =
|
||||||
Arg_spec.of_result_map requires ~f:(fun libs ->
|
Arg_spec.of_result_map requires ~f:(fun libs ->
|
||||||
let paths =
|
let paths =
|
||||||
|
@ -159,11 +161,12 @@ module Gen (S : sig val sctx : SC.t end) = struct
|
||||||
Arg_spec.S (List.concat_map (Path.Set.to_list paths)
|
Arg_spec.S (List.concat_map (Path.Set.to_list paths)
|
||||||
~f:(fun dir -> [Arg_spec.A "-I"; Path dir])))
|
~f:(fun dir -> [Arg_spec.A "-I"; Path dir])))
|
||||||
|
|
||||||
let to_html (odoc_file : odoc) ~deps ~requires =
|
let setup_html (odoc_file : odoc) ~requires =
|
||||||
|
let deps = Dep.deps requires in
|
||||||
let to_remove, jbuilder_keep =
|
let to_remove, jbuilder_keep =
|
||||||
match odoc_file.typ with
|
match odoc_file.source with
|
||||||
| `Mld -> odoc_file.html_file, []
|
| Mld -> odoc_file.html_file, []
|
||||||
| `Module ->
|
| Module ->
|
||||||
let jbuilder_keep =
|
let jbuilder_keep =
|
||||||
Build.create_file (odoc_file.html_dir ++ Config.jbuilder_keep_fname) in
|
Build.create_file (odoc_file.html_dir ++ Config.jbuilder_keep_fname) in
|
||||||
odoc_file.html_dir, [jbuilder_keep]
|
odoc_file.html_dir, [jbuilder_keep]
|
||||||
|
@ -182,10 +185,7 @@ module Gen (S : sig val sctx : SC.t end) = struct
|
||||||
; Dep odoc_file.odoc_input
|
; Dep odoc_file.odoc_input
|
||||||
; Hidden_targets [odoc_file.html_file]
|
; Hidden_targets [odoc_file.html_file]
|
||||||
]
|
]
|
||||||
:: jbuilder_keep
|
:: jbuilder_keep))
|
||||||
)
|
|
||||||
);
|
|
||||||
odoc_file.html_file
|
|
||||||
|
|
||||||
let css_file = Paths.html_root ++ "odoc.css"
|
let css_file = Paths.html_root ++ "odoc.css"
|
||||||
|
|
||||||
|
@ -259,12 +259,6 @@ module Gen (S : sig val sctx : SC.t end) = struct
|
||||||
in
|
in
|
||||||
SC.add_rule sctx @@ Build.write_file toplevel_index html
|
SC.add_rule sctx @@ Build.write_file toplevel_index html
|
||||||
|
|
||||||
|
|
||||||
let html_alias pkg =
|
|
||||||
Build_system.Alias.doc ~dir:(
|
|
||||||
Path.append context.build_dir pkg.Package.path
|
|
||||||
)
|
|
||||||
|
|
||||||
let libs_of_pkg ~pkg =
|
let libs_of_pkg ~pkg =
|
||||||
match Package.Name.Map.find (SC.libs_by_package sctx) pkg with
|
match Package.Name.Map.find (SC.libs_by_package sctx) pkg with
|
||||||
| None -> Lib.Set.empty
|
| None -> Lib.Set.empty
|
||||||
|
@ -278,7 +272,6 @@ module Gen (S : sig val sctx : SC.t end) = struct
|
||||||
pkg_libs
|
pkg_libs
|
||||||
|
|
||||||
let create_odoc ~target odoc_input =
|
let create_odoc ~target odoc_input =
|
||||||
let html_alias = Dep.html_alias target in
|
|
||||||
let html_base = Paths.html target in
|
let html_base = Paths.html target in
|
||||||
match target with
|
match target with
|
||||||
| Lib _ ->
|
| Lib _ ->
|
||||||
|
@ -291,8 +284,7 @@ module Gen (S : sig val sctx : SC.t end) = struct
|
||||||
{ odoc_input
|
{ odoc_input
|
||||||
; html_dir
|
; html_dir
|
||||||
; html_file = html_dir ++ "index.html"
|
; html_file = html_dir ++ "index.html"
|
||||||
; typ = `Module
|
; source = Module
|
||||||
; html_alias
|
|
||||||
}
|
}
|
||||||
| Pkg _ ->
|
| Pkg _ ->
|
||||||
{ odoc_input
|
{ odoc_input
|
||||||
|
@ -303,52 +295,48 @@ module Gen (S : sig val sctx : SC.t end) = struct
|
||||||
|> String.drop_prefix ~prefix:"page-"
|
|> String.drop_prefix ~prefix:"page-"
|
||||||
|> Option.value_exn
|
|> Option.value_exn
|
||||||
)
|
)
|
||||||
; typ = `Mld
|
; source = Mld
|
||||||
; html_alias
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let static_html = [ css_file; toplevel_index ]
|
||||||
|
|
||||||
|
let odocs =
|
||||||
|
let odoc_glob =
|
||||||
|
Re.compile (Re.seq [Re.(rep1 any) ; Re.str ".odoc" ; Re.eos]) in
|
||||||
|
fun target ->
|
||||||
|
let dir = Paths.odocs target in
|
||||||
|
SC.eval_glob sctx ~dir odoc_glob
|
||||||
|
|> List.map ~f:(fun d -> create_odoc (Path.relative dir d) ~target)
|
||||||
|
|
||||||
|
let setup_lib_html_rules =
|
||||||
|
let loaded = ref Lib.Set.empty in
|
||||||
|
fun lib ~requires ->
|
||||||
|
if not (Lib.Set.mem !loaded lib) then begin
|
||||||
|
loaded := Lib.Set.add !loaded lib;
|
||||||
|
let odocs = odocs (Lib lib) in
|
||||||
|
List.iter odocs ~f:(setup_html ~requires);
|
||||||
|
let html_files = List.map ~f:(fun o -> o.html_file) odocs in
|
||||||
|
SC.add_alias_deps sctx (Dep.html_alias (Lib lib))
|
||||||
|
(Path.Set.of_list (List.rev_append static_html html_files));
|
||||||
|
end
|
||||||
|
|
||||||
let setup_pkg_html_rules =
|
let setup_pkg_html_rules =
|
||||||
let loaded = Package.Name.Table.create ~default_value:false in
|
let loaded = Package.Name.Table.create ~default_value:false in
|
||||||
let odoc_glob =
|
|
||||||
Re.compile (Re.seq [Re.(rep1 any) ; Re.str ".odoc" ; Re.eos]) in
|
|
||||||
fun ~pkg ~libs ->
|
fun ~pkg ~libs ->
|
||||||
if not (Package.Name.Table.get loaded pkg) then begin
|
if not (Package.Name.Table.get loaded pkg) then begin
|
||||||
Package.Name.Table.set loaded ~key:pkg ~data:true;
|
Package.Name.Table.set loaded ~key:pkg ~data:true;
|
||||||
|
let requires = Lib.closure libs in
|
||||||
|
List.iter libs ~f:(setup_lib_html_rules ~requires);
|
||||||
|
let pkg_odocs = odocs (Pkg pkg) in
|
||||||
|
List.iter pkg_odocs ~f:(setup_html ~requires);
|
||||||
let odocs =
|
let odocs =
|
||||||
let odocs target =
|
|
||||||
let dir = Paths.odocs target in
|
|
||||||
SC.eval_glob sctx ~dir odoc_glob
|
|
||||||
|> List.map ~f:(fun d -> create_odoc (Path.relative dir d) ~target)
|
|
||||||
in
|
|
||||||
List.concat (
|
List.concat (
|
||||||
odocs (Pkg pkg)
|
pkg_odocs
|
||||||
:: (List.map libs ~f:(fun lib -> odocs (Lib lib)))
|
:: (List.map libs ~f:(fun lib -> odocs (Lib lib)))
|
||||||
) in
|
) in
|
||||||
let html_files =
|
let html_files = List.map ~f:(fun o -> o.html_file) odocs in
|
||||||
let closure =
|
SC.add_alias_deps sctx (Dep.html_alias (Pkg pkg))
|
||||||
match Lib.closure libs with
|
(Path.Set.of_list (List.rev_append static_html html_files))
|
||||||
| Ok closure -> closure
|
|
||||||
| Error _ ->
|
|
||||||
(* CR diml for rgrinberg: this branch needs a comment, I
|
|
||||||
don't understand why we fallback to not taking the
|
|
||||||
transitive closure in case of error. *)
|
|
||||||
libs
|
|
||||||
in
|
|
||||||
let deps = Dep.deps (Ok closure) in
|
|
||||||
List.map odocs ~f:(to_html ~deps ~requires:(Ok closure)) in
|
|
||||||
List.iter (
|
|
||||||
Dep.html_alias (Pkg pkg)
|
|
||||||
:: List.map ~f:(fun lib -> Dep.html_alias (Lib lib)) libs
|
|
||||||
) ~f:(fun alias ->
|
|
||||||
SC.add_alias_deps sctx alias
|
|
||||||
(Path.Set.of_list [ css_file
|
|
||||||
; toplevel_index
|
|
||||||
])
|
|
||||||
);
|
|
||||||
List.combine odocs html_files
|
|
||||||
|> List.iter ~f:(fun (odoc, html) ->
|
|
||||||
SC.add_alias_deps sctx odoc.html_alias (Path.Set.singleton html)
|
|
||||||
);
|
|
||||||
end
|
end
|
||||||
|
|
||||||
let gen_rules ~dir:_ rest =
|
let gen_rules ~dir:_ rest =
|
||||||
|
@ -366,25 +354,31 @@ module Gen (S : sig val sctx : SC.t end) = struct
|
||||||
| Ok lib -> SC.load_dir sctx ~dir:(Lib.src_dir lib)
|
| Ok lib -> SC.load_dir sctx ~dir:(Lib.src_dir lib)
|
||||||
end
|
end
|
||||||
| "_html" :: lib_unique_name_or_pkg :: _ ->
|
| "_html" :: lib_unique_name_or_pkg :: _ ->
|
||||||
let setup_html_rules pkg =
|
|
||||||
setup_pkg_html_rules ~pkg ~libs:(
|
|
||||||
Lib.Set.to_list (load_all_odoc_rules_pkg ~pkg)
|
|
||||||
) in
|
|
||||||
(* TODO we can be a better with the error handling in the case where
|
(* TODO we can be a better with the error handling in the case where
|
||||||
lib_unique_name_or_pkg is neither a valid pkg or lnu *)
|
lib_unique_name_or_pkg is neither a valid pkg or lnu *)
|
||||||
let lib, lib_db = SC.Scope_key.of_string sctx lib_unique_name_or_pkg in
|
let lib, lib_db = SC.Scope_key.of_string sctx lib_unique_name_or_pkg in
|
||||||
|
let setup_pkg_html_rules pkg =
|
||||||
|
setup_pkg_html_rules ~pkg ~libs:(
|
||||||
|
Lib.Set.to_list (load_all_odoc_rules_pkg ~pkg)) in
|
||||||
begin match Lib.DB.find lib_db lib with
|
begin match Lib.DB.find lib_db lib with
|
||||||
| Error _ -> ()
|
| Error _ -> ()
|
||||||
| Ok lib -> Option.iter (Lib.package lib) ~f:setup_html_rules
|
| Ok lib ->
|
||||||
|
begin match Lib.package lib with
|
||||||
|
| None -> setup_lib_html_rules lib ~requires:(Lib.closure [lib])
|
||||||
|
| Some pkg -> setup_pkg_html_rules pkg
|
||||||
|
end
|
||||||
end;
|
end;
|
||||||
Option.iter
|
Option.iter
|
||||||
(Package.Name.Map.find (SC.packages sctx)
|
(Package.Name.Map.find (SC.packages sctx)
|
||||||
(Package.Name.of_string lib_unique_name_or_pkg))
|
(Package.Name.of_string lib_unique_name_or_pkg))
|
||||||
~f:(fun pkg -> setup_html_rules pkg.name)
|
~f:(fun pkg -> setup_pkg_html_rules pkg.name)
|
||||||
| _ -> ()
|
| _ -> ()
|
||||||
|
|
||||||
let setup_package_aliases (pkg : Package.t) =
|
let setup_package_aliases (pkg : Package.t) =
|
||||||
let alias = html_alias pkg in
|
let alias =
|
||||||
|
Build_system.Alias.doc ~dir:(
|
||||||
|
Path.append context.build_dir pkg.Package.path
|
||||||
|
) in
|
||||||
SC.add_alias_deps sctx alias (
|
SC.add_alias_deps sctx alias (
|
||||||
Dep.html_alias (Pkg pkg.name)
|
Dep.html_alias (Pkg pkg.name)
|
||||||
:: (libs_of_pkg ~pkg:pkg.name
|
:: (libs_of_pkg ~pkg:pkg.name
|
||||||
|
@ -468,7 +462,7 @@ module Gen (S : sig val sctx : SC.t end) = struct
|
||||||
let init ~modules_by_lib ~mlds_of_dir =
|
let init ~modules_by_lib ~mlds_of_dir =
|
||||||
let docs_by_package =
|
let docs_by_package =
|
||||||
let map = lazy (
|
let map = lazy (
|
||||||
SC.stanzas sctx
|
stanzas
|
||||||
|> List.concat_map ~f:(fun (w : SC.Dir_with_jbuild.t) ->
|
|> List.concat_map ~f:(fun (w : SC.Dir_with_jbuild.t) ->
|
||||||
List.filter_map w.stanzas ~f:(function
|
List.filter_map w.stanzas ~f:(function
|
||||||
| Documentation (d : Jbuild.Documentation.t) ->
|
| Documentation (d : Jbuild.Documentation.t) ->
|
||||||
|
@ -491,7 +485,7 @@ module Gen (S : sig val sctx : SC.t end) = struct
|
||||||
| o -> o
|
| o -> o
|
||||||
end) in
|
end) in
|
||||||
let lib_to_library = lazy (
|
let lib_to_library = lazy (
|
||||||
SC.stanzas sctx
|
stanzas
|
||||||
|> List.concat_map ~f:(fun (w : SC.Dir_with_jbuild.t) ->
|
|> List.concat_map ~f:(fun (w : SC.Dir_with_jbuild.t) ->
|
||||||
List.filter_map w.stanzas ~f:(function
|
List.filter_map w.stanzas ~f:(function
|
||||||
| Jbuild.Library (l : Library.t) ->
|
| Jbuild.Library (l : Library.t) ->
|
||||||
|
@ -529,7 +523,7 @@ module Gen (S : sig val sctx : SC.t end) = struct
|
||||||
Super_context.add_alias_deps
|
Super_context.add_alias_deps
|
||||||
sctx
|
sctx
|
||||||
(Build_system.Alias.private_doc ~dir:context.build_dir)
|
(Build_system.Alias.private_doc ~dir:context.build_dir)
|
||||||
(SC.stanzas sctx
|
(stanzas
|
||||||
|> List.concat_map ~f:(fun (w : SC.Dir_with_jbuild.t) ->
|
|> List.concat_map ~f:(fun (w : SC.Dir_with_jbuild.t) ->
|
||||||
List.filter_map w.stanzas ~f:(function
|
List.filter_map w.stanzas ~f:(function
|
||||||
| Jbuild.Library (l : Jbuild.Library.t) ->
|
| Jbuild.Library (l : Jbuild.Library.t) ->
|
||||||
|
@ -544,7 +538,7 @@ module Gen (S : sig val sctx : SC.t end) = struct
|
||||||
| _ -> None
|
| _ -> None
|
||||||
))
|
))
|
||||||
|> List.map ~f:(fun (lib : Lib.t) ->
|
|> List.map ~f:(fun (lib : Lib.t) ->
|
||||||
Build_system.Alias.stamp_file (Dep.alias (Lib lib)))
|
Build_system.Alias.stamp_file (Dep.html_alias (Lib lib)))
|
||||||
|> Path.Set.of_list
|
|> Path.Set.of_list
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
This test checks that there is no clash when two private libraries have the same name
|
This test checks that there is no clash when two private libraries have the same name
|
||||||
|
|
||||||
$ dune build --display short @doc-private
|
$ dune build --display short @doc-private
|
||||||
|
odoc _doc/_html/odoc.css
|
||||||
ocamldep a/test.ml.d
|
ocamldep a/test.ml.d
|
||||||
ocamlc a/.test.objs/test.{cmi,cmo,cmt}
|
ocamlc a/.test.objs/test.{cmi,cmo,cmt}
|
||||||
odoc _doc/_odoc/lib/test@a/test.odoc
|
odoc _doc/_odoc/lib/test@a/test.odoc
|
||||||
|
odoc _doc/_html/test@a/Test/.jbuilder-keep,_doc/_html/test@a/Test/index.html
|
||||||
ocamldep b/test.ml.d
|
ocamldep b/test.ml.d
|
||||||
ocamlc b/.test.objs/test.{cmi,cmo,cmt}
|
ocamlc b/.test.objs/test.{cmi,cmo,cmt}
|
||||||
odoc _doc/_odoc/lib/test@b/test.odoc
|
odoc _doc/_odoc/lib/test@b/test.odoc
|
||||||
|
odoc _doc/_html/test@b/Test/.jbuilder-keep,_doc/_html/test@b/Test/index.html
|
||||||
|
|
Loading…
Reference in New Issue