2016-02-18 07:11:59 -08:00
|
|
|
(**************************************************************************)
|
|
|
|
(* *)
|
|
|
|
(* OCaml *)
|
|
|
|
(* *)
|
|
|
|
(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
|
|
|
|
(* *)
|
|
|
|
(* Copyright 2001 Institut National de Recherche en Informatique et *)
|
|
|
|
(* en Automatique. *)
|
|
|
|
(* *)
|
|
|
|
(* All rights reserved. This file is distributed under the terms of *)
|
|
|
|
(* the GNU Lesser General Public License version 2.1, with the *)
|
|
|
|
(* special exception on linking described in the file LICENSE. *)
|
|
|
|
(* *)
|
|
|
|
(**************************************************************************)
|
2002-03-27 08:20:32 -08:00
|
|
|
|
|
|
|
(** Top modules dependencies. *)
|
|
|
|
|
|
|
|
module Module = Odoc_module
|
|
|
|
module Type = Odoc_type
|
2018-07-23 05:19:41 -07:00
|
|
|
module String = Misc.Stdlib.String
|
2002-03-27 08:20:32 -08:00
|
|
|
|
|
|
|
let set_to_list s =
|
|
|
|
let l = ref [] in
|
2018-07-23 05:19:41 -07:00
|
|
|
String.Set.iter (fun e -> l := e :: !l) s;
|
2002-03-27 08:20:32 -08:00
|
|
|
!l
|
|
|
|
|
|
|
|
let impl_dependencies ast =
|
2018-07-23 05:19:41 -07:00
|
|
|
Depend.free_structure_names := String.Set.empty;
|
|
|
|
Depend.add_use_file String.Map.empty [Parsetree.Ptop_def ast];
|
2002-03-27 08:20:32 -08:00
|
|
|
set_to_list !Depend.free_structure_names
|
|
|
|
|
|
|
|
let intf_dependencies ast =
|
2018-07-23 05:19:41 -07:00
|
|
|
Depend.free_structure_names := String.Set.empty;
|
|
|
|
Depend.add_signature String.Map.empty ast;
|
2002-03-27 08:20:32 -08:00
|
|
|
set_to_list !Depend.free_structure_names
|
|
|
|
|
|
|
|
|
2010-01-22 04:48:24 -08:00
|
|
|
module Dep =
|
2002-03-27 08:20:32 -08:00
|
|
|
struct
|
|
|
|
type id = string
|
|
|
|
|
|
|
|
let set_to_list s =
|
|
|
|
let l = ref [] in
|
2018-07-23 05:19:41 -07:00
|
|
|
String.Set.iter (fun e -> l := e :: !l) s;
|
2002-03-27 08:20:32 -08:00
|
|
|
!l
|
|
|
|
|
|
|
|
type node = {
|
2002-07-23 07:12:03 -07:00
|
|
|
id : id ;
|
2018-07-23 05:19:41 -07:00
|
|
|
mutable near : String.Set.t ; (** direct children *)
|
|
|
|
mutable far : (id * String.Set.t) list ; (** indirect children, from which children path *)
|
2010-01-22 04:48:24 -08:00
|
|
|
reflex : bool ; (** reflexive or not, we keep
|
2002-07-23 07:12:03 -07:00
|
|
|
information here to remove the node itself from its direct children *)
|
2002-03-27 08:20:32 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
type graph = node list
|
|
|
|
|
|
|
|
let make_node s children =
|
|
|
|
let set = List.fold_right
|
2018-07-23 05:19:41 -07:00
|
|
|
String.Set.add
|
2002-07-23 07:12:03 -07:00
|
|
|
children
|
2018-07-23 05:19:41 -07:00
|
|
|
String.Set.empty
|
2002-03-27 08:20:32 -08:00
|
|
|
in
|
2010-01-22 04:48:24 -08:00
|
|
|
{ id = s;
|
2018-07-23 05:19:41 -07:00
|
|
|
near = String.Set.remove s set ;
|
2002-07-23 07:12:03 -07:00
|
|
|
far = [] ;
|
|
|
|
reflex = List.mem s children ;
|
2002-03-27 08:20:32 -08:00
|
|
|
}
|
|
|
|
|
2010-01-22 04:48:24 -08:00
|
|
|
let get_node graph s =
|
2002-03-27 08:20:32 -08:00
|
|
|
try List.find (fun n -> n.id = s) graph
|
2010-01-22 04:48:24 -08:00
|
|
|
with Not_found ->
|
2002-07-23 07:12:03 -07:00
|
|
|
make_node s []
|
2002-03-27 08:20:32 -08:00
|
|
|
|
|
|
|
let rec trans_closure graph acc n =
|
2018-07-23 05:19:41 -07:00
|
|
|
if String.Set.mem n.id acc then
|
2002-07-23 07:12:03 -07:00
|
|
|
acc
|
2002-03-27 08:20:32 -08:00
|
|
|
else
|
2015-10-09 13:41:51 -07:00
|
|
|
(* potential optimisation: use far field if nonempty? *)
|
2018-07-23 05:19:41 -07:00
|
|
|
String.Set.fold
|
2002-07-23 07:12:03 -07:00
|
|
|
(fun child -> fun acc2 ->
|
|
|
|
trans_closure graph acc2 (get_node graph child))
|
|
|
|
n.near
|
2018-07-23 05:19:41 -07:00
|
|
|
(String.Set.add n.id acc)
|
2010-01-22 04:48:24 -08:00
|
|
|
|
2002-03-27 08:20:32 -08:00
|
|
|
let node_trans_closure graph n =
|
|
|
|
let far = List.map
|
2010-01-22 04:48:24 -08:00
|
|
|
(fun child ->
|
2018-07-23 05:19:41 -07:00
|
|
|
let set = trans_closure graph String.Set.empty (get_node graph child) in
|
2002-07-23 07:12:03 -07:00
|
|
|
(child, set)
|
|
|
|
)
|
|
|
|
(set_to_list n.near)
|
2002-03-27 08:20:32 -08:00
|
|
|
in
|
|
|
|
n.far <- far
|
|
|
|
|
|
|
|
let compute_trans_closure graph =
|
|
|
|
List.iter (node_trans_closure graph) graph
|
|
|
|
|
|
|
|
let prune_node graph node =
|
2018-07-23 05:19:41 -07:00
|
|
|
String.Set.iter
|
2002-07-23 07:12:03 -07:00
|
|
|
(fun child ->
|
|
|
|
let set_reachables = List.fold_left
|
|
|
|
(fun acc -> fun (ch, reachables) ->
|
|
|
|
if child = ch then
|
|
|
|
acc
|
|
|
|
else
|
2018-07-23 05:19:41 -07:00
|
|
|
String.Set.union acc reachables
|
2002-07-23 07:12:03 -07:00
|
|
|
)
|
2018-07-23 05:19:41 -07:00
|
|
|
String.Set.empty
|
2002-07-23 07:12:03 -07:00
|
|
|
node.far
|
|
|
|
in
|
2018-07-23 05:19:41 -07:00
|
|
|
let set = String.Set.remove node.id set_reachables in
|
|
|
|
if String.Set.exists (fun n2 -> String.Set.mem child (get_node graph n2).near) set then
|
2002-07-23 07:12:03 -07:00
|
|
|
(
|
2018-07-23 05:19:41 -07:00
|
|
|
node.near <- String.Set.remove child node.near ;
|
2002-07-23 07:12:03 -07:00
|
|
|
node.far <- List.filter (fun (ch,_) -> ch <> child) node.far
|
|
|
|
)
|
|
|
|
else
|
|
|
|
()
|
|
|
|
)
|
|
|
|
node.near;
|
2010-01-22 04:48:24 -08:00
|
|
|
if node.reflex then
|
2018-07-23 05:19:41 -07:00
|
|
|
node.near <- String.Set.add node.id node.near
|
2002-03-27 08:20:32 -08:00
|
|
|
else
|
2002-07-23 07:12:03 -07:00
|
|
|
()
|
2002-03-27 08:20:32 -08:00
|
|
|
|
|
|
|
let kernel graph =
|
|
|
|
(* compute transitive closure *)
|
|
|
|
compute_trans_closure graph ;
|
|
|
|
|
|
|
|
(* remove edges to keep a transitive kernel *)
|
|
|
|
List.iter (prune_node graph) graph;
|
|
|
|
|
|
|
|
graph
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
(** [type_deps t] returns the list of fully qualified type names
|
|
|
|
[t] depends on. *)
|
|
|
|
let type_deps t =
|
|
|
|
let module T = Odoc_type in
|
|
|
|
let l = ref [] in
|
|
|
|
let re = Str.regexp "\\([A-Z]\\([a-zA-Z_'0-9]\\)*\\.\\)+\\([a-z][a-zA-Z_'0-9]*\\)" in
|
2010-01-22 04:48:24 -08:00
|
|
|
let f s =
|
2002-03-27 08:20:32 -08:00
|
|
|
let s2 = Str.matched_string s in
|
2010-01-22 04:48:24 -08:00
|
|
|
l := s2 :: !l ;
|
2002-03-27 08:20:32 -08:00
|
|
|
s2
|
|
|
|
in
|
2014-10-14 08:51:30 -07:00
|
|
|
let ty t =
|
|
|
|
let s = Odoc_print.string_of_type_expr t in
|
|
|
|
ignore (Str.global_substitute re f s)
|
|
|
|
in
|
2002-03-27 08:20:32 -08:00
|
|
|
(match t.T.ty_kind with
|
|
|
|
T.Type_abstract -> ()
|
2007-10-09 03:29:37 -07:00
|
|
|
| T.Type_variant cl ->
|
2002-03-27 08:20:32 -08:00
|
|
|
List.iter
|
2002-07-23 07:12:03 -07:00
|
|
|
(fun c ->
|
2014-10-14 08:51:30 -07:00
|
|
|
match c.T.vc_args with
|
|
|
|
| T.Cstr_tuple l -> List.iter ty l
|
|
|
|
| T.Cstr_record l -> List.iter (fun r -> ty r.T.rf_type) l
|
2002-07-23 07:12:03 -07:00
|
|
|
)
|
|
|
|
cl
|
2007-10-09 03:29:37 -07:00
|
|
|
| T.Type_record rl ->
|
2014-10-14 08:51:30 -07:00
|
|
|
List.iter (fun r -> ty r.T.rf_type) rl
|
2014-05-04 16:08:45 -07:00
|
|
|
| T.Type_open -> ()
|
2002-03-27 08:20:32 -08:00
|
|
|
);
|
|
|
|
|
|
|
|
(match t.T.ty_manifest with
|
|
|
|
None -> ()
|
2014-05-22 06:38:29 -07:00
|
|
|
| Some (T.Object_type fields) ->
|
2014-10-14 08:51:30 -07:00
|
|
|
List.iter (fun r -> ty r.T.of_type) fields
|
2014-05-22 06:38:29 -07:00
|
|
|
| Some (T.Other e) ->
|
2014-10-14 08:51:30 -07:00
|
|
|
ty e
|
2002-03-27 08:20:32 -08:00
|
|
|
);
|
|
|
|
|
|
|
|
!l
|
|
|
|
|
2017-08-10 03:59:23 -07:00
|
|
|
(** Modify the module dependencies of the given list of modules,
|
2002-03-27 08:20:32 -08:00
|
|
|
to get the minimum transitivity kernel. *)
|
|
|
|
let kernel_deps_of_modules modules =
|
|
|
|
let graph = List.map
|
|
|
|
(fun m -> Dep.make_node m.Module.m_name m.Module.m_top_deps)
|
|
|
|
modules
|
|
|
|
in
|
|
|
|
let k = Dep.kernel graph in
|
2010-01-22 04:48:24 -08:00
|
|
|
List.iter
|
2002-03-27 08:20:32 -08:00
|
|
|
(fun m ->
|
|
|
|
let node = Dep.get_node k m.Module.m_name in
|
2010-01-22 04:48:24 -08:00
|
|
|
m.Module.m_top_deps <-
|
2018-07-23 05:19:41 -07:00
|
|
|
List.filter (fun m2 -> String.Set.mem m2 node.Dep.near) m.Module.m_top_deps)
|
2002-03-27 08:20:32 -08:00
|
|
|
modules
|
|
|
|
|
|
|
|
(** Return the list of dependencies between the given types,
|
|
|
|
in the form of a list [(type, names of types it depends on)].
|
|
|
|
@param kernel indicates if we must keep only the transitivity kernel
|
|
|
|
of the dependencies. Default is [false].
|
|
|
|
*)
|
|
|
|
let deps_of_types ?(kernel=false) types =
|
|
|
|
let deps_pre = List.map (fun t -> (t, type_deps t)) types in
|
2016-01-19 15:02:30 -08:00
|
|
|
if kernel then
|
|
|
|
(
|
|
|
|
let graph = List.map
|
|
|
|
(fun (t, names) -> Dep.make_node t.Type.ty_name names)
|
|
|
|
deps_pre
|
|
|
|
in
|
|
|
|
let k = Dep.kernel graph in
|
|
|
|
List.map
|
|
|
|
(fun t ->
|
2002-07-23 07:12:03 -07:00
|
|
|
let node = Dep.get_node k t.Type.ty_name in
|
|
|
|
(t, Dep.set_to_list node.Dep.near)
|
2016-01-19 15:02:30 -08:00
|
|
|
)
|
|
|
|
types
|
|
|
|
)
|
|
|
|
else
|
|
|
|
deps_pre
|