summaryrefslogtreecommitdiff
path: root/ocaml-binary-annot/ocamldoc/odoc_cross.ml
diff options
context:
space:
mode:
Diffstat (limited to 'ocaml-binary-annot/ocamldoc/odoc_cross.ml')
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_cross.ml1006
1 files changed, 1006 insertions, 0 deletions
diff --git a/ocaml-binary-annot/ocamldoc/odoc_cross.ml b/ocaml-binary-annot/ocamldoc/odoc_cross.ml
new file mode 100644
index 0000000000..39965f83b2
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_cross.ml
@@ -0,0 +1,1006 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* 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 Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** Cross referencing. *)
+
+module Name = Odoc_name
+open Odoc_module
+open Odoc_class
+open Odoc_exception
+open Odoc_types
+open Odoc_value
+open Odoc_type
+open Odoc_parameter
+
+(*** Replacements of aliases : if e1 = e2 and e2 = e3, then replace e2 by e3 to have e1 = e3,
+ in order to associate the element with complete information. *)
+
+(** The module used to keep what refs were modified. *)
+module S = Set.Make
+ (
+ struct type t = string * ref_kind option
+ let compare = Pervasives.compare
+ end
+ )
+
+let verified_refs = ref S.empty
+
+let add_verified v = verified_refs := S.add v !verified_refs
+let was_verified v = S.mem v !verified_refs
+
+(** The module with the predicates used to get the aliased modules, classes and exceptions. *)
+module P_alias =
+ struct
+ type t = int
+
+ let p_module m _ =
+ (true,
+ match m.m_kind with
+ Module_alias _ -> true
+ | _ -> false
+ )
+ let p_module_type mt _ =
+ (true,
+ match mt.mt_kind with
+ Some (Module_type_alias _) -> true
+ | _ -> false
+ )
+ let p_class c _ = (false, false)
+ let p_class_type ct _ = (false, false)
+ let p_value v _ = false
+ let p_type t _ = false
+ let p_exception e _ = e.ex_alias <> None
+ let p_attribute a _ = false
+ let p_method m _ = false
+ let p_section s _ = false
+ end
+
+(** The module used to get the aliased elements. *)
+module Search_alias = Odoc_search.Search (P_alias)
+
+type alias_state =
+ Alias_resolved
+ | Alias_to_resolve
+
+(** Couples of module name aliases. *)
+let (module_aliases : (Name.t, Name.t * alias_state) Hashtbl.t) = Hashtbl.create 13 ;;
+
+(** Couples of module or module type name aliases. *)
+let module_and_modtype_aliases = Hashtbl.create 13;;
+
+(** Couples of exception name aliases. *)
+let exception_aliases = Hashtbl.create 13;;
+
+let rec build_alias_list = function
+ [] -> ()
+ | (Odoc_search.Res_module m) :: q ->
+ (
+ match m.m_kind with
+ Module_alias ma ->
+ Hashtbl.add module_aliases m.m_name (ma.ma_name, Alias_to_resolve);
+ Hashtbl.add module_and_modtype_aliases m.m_name (ma.ma_name, Alias_to_resolve)
+ | _ -> ()
+ );
+ build_alias_list q
+ | (Odoc_search.Res_module_type mt) :: q ->
+ (
+ match mt.mt_kind with
+ Some (Module_type_alias mta) ->
+ Hashtbl.add module_and_modtype_aliases
+ mt.mt_name (mta.mta_name, Alias_to_resolve)
+ | _ -> ()
+ );
+ build_alias_list q
+ | (Odoc_search.Res_exception e) :: q ->
+ (
+ match e.ex_alias with
+ None -> ()
+ | Some ea ->
+ Hashtbl.add exception_aliases
+ e.ex_name (ea.ea_name,Alias_to_resolve)
+ );
+ build_alias_list q
+ | _ :: q ->
+ build_alias_list q
+
+(** Retrieve the aliases for modules, module types and exceptions
+ and put them in global hash tables. *)
+let get_alias_names module_list =
+ Hashtbl.clear module_aliases;
+ Hashtbl.clear module_and_modtype_aliases;
+ Hashtbl.clear exception_aliases;
+ build_alias_list (Search_alias.search module_list 0)
+
+exception Found of string
+let name_alias =
+ let rec f t name =
+ try
+ match Hashtbl.find t name with
+ (s, Alias_resolved) -> s
+ | (s, Alias_to_resolve) -> f t s
+ with
+ Not_found ->
+ try
+ Hashtbl.iter
+ (fun n2 (n3, _) ->
+ if Name.prefix n2 name then
+ let ln2 = String.length n2 in
+ let s = n3^(String.sub name ln2 ((String.length name) - ln2)) in
+ raise (Found s)
+ )
+ t ;
+ Hashtbl.replace t name (name, Alias_resolved);
+ name
+ with
+ Found s ->
+ let s2 = f t s in
+ Hashtbl.replace t s2 (s2, Alias_resolved);
+ s2
+ in
+ fun name alias_tbl ->
+ f alias_tbl name
+
+
+module Map_ord =
+ struct
+ type t = string
+ let compare = Pervasives.compare
+ end
+
+module Ele_map = Map.Make (Map_ord)
+
+let known_elements = ref Ele_map.empty
+let add_known_element name k =
+ try
+ let l = Ele_map.find name !known_elements in
+ let s = Ele_map.remove name !known_elements in
+ known_elements := Ele_map.add name (k::l) s
+ with
+ Not_found ->
+ known_elements := Ele_map.add name [k] !known_elements
+
+let rec get_known_elements name =
+ try Ele_map.find name !known_elements
+ with Not_found -> []
+
+let kind_name_exists kind =
+ let pred =
+ match kind with
+ RK_module -> (fun e -> match e with Odoc_search.Res_module _ -> true | _ -> false)
+ | RK_module_type -> (fun e -> match e with Odoc_search.Res_module_type _ -> true | _ -> false)
+ | RK_class -> (fun e -> match e with Odoc_search.Res_class_type _ -> true | _ -> false)
+ | RK_class_type -> (fun e -> match e with Odoc_search.Res_class_type _ -> true | _ -> false)
+ | RK_value -> (fun e -> match e with Odoc_search.Res_value _ -> true | _ -> false)
+ | RK_type -> (fun e -> match e with Odoc_search.Res_type _ -> true | _ -> false)
+ | RK_exception -> (fun e -> match e with Odoc_search.Res_exception _ -> true | _ -> false)
+ | RK_attribute -> (fun e -> match e with Odoc_search.Res_attribute _ -> true | _ -> false)
+ | RK_method -> (fun e -> match e with Odoc_search.Res_method _ -> true | _ -> false)
+ | RK_section _ -> assert false
+ in
+ fun name ->
+ try List.exists pred (get_known_elements name)
+ with Not_found -> false
+
+let module_exists = kind_name_exists RK_module
+let module_type_exists = kind_name_exists RK_module_type
+let class_exists = kind_name_exists RK_class
+let class_type_exists = kind_name_exists RK_class_type
+let value_exists = kind_name_exists RK_value
+let type_exists = kind_name_exists RK_type
+let exception_exists = kind_name_exists RK_exception
+let attribute_exists = kind_name_exists RK_attribute
+let method_exists = kind_name_exists RK_method
+
+let lookup_module name =
+ match List.find
+ (fun k -> match k with Odoc_search.Res_module _ -> true | _ -> false)
+ (get_known_elements name)
+ with
+ | Odoc_search.Res_module m -> m
+ | _ -> assert false
+
+let lookup_module_type name =
+ match List.find
+ (fun k -> match k with Odoc_search.Res_module_type _ -> true | _ -> false)
+ (get_known_elements name)
+ with
+ | Odoc_search.Res_module_type m -> m
+ | _ -> assert false
+
+let lookup_class name =
+ match List.find
+ (fun k -> match k with Odoc_search.Res_class _ -> true | _ -> false)
+ (get_known_elements name)
+ with
+ | Odoc_search.Res_class c -> c
+ | _ -> assert false
+
+let lookup_class_type name =
+ match List.find
+ (fun k -> match k with Odoc_search.Res_class_type _ -> true | _ -> false)
+ (get_known_elements name)
+ with
+ | Odoc_search.Res_class_type c -> c
+ | _ -> assert false
+
+let lookup_exception name =
+ match List.find
+ (fun k -> match k with Odoc_search.Res_exception _ -> true | _ -> false)
+ (get_known_elements name)
+ with
+ | Odoc_search.Res_exception e -> e
+ | _ -> assert false
+
+class scan =
+ object
+ inherit Odoc_scan.scanner
+ method! scan_value v =
+ add_known_element v.val_name (Odoc_search.Res_value v)
+ method! scan_type t =
+ add_known_element t.ty_name (Odoc_search.Res_type t)
+ method! scan_exception e =
+ add_known_element e.ex_name (Odoc_search.Res_exception e)
+ method! scan_attribute a =
+ add_known_element a.att_value.val_name
+ (Odoc_search.Res_attribute a)
+ method! scan_method m =
+ add_known_element m.met_value.val_name
+ (Odoc_search.Res_method m)
+ method! scan_class_pre c =
+ add_known_element c.cl_name (Odoc_search.Res_class c);
+ true
+ method! scan_class_type_pre c =
+ add_known_element c.clt_name (Odoc_search.Res_class_type c);
+ true
+ method! scan_module_pre m =
+ add_known_element m.m_name (Odoc_search.Res_module m);
+ true
+ method! scan_module_type_pre m =
+ add_known_element m.mt_name (Odoc_search.Res_module_type m);
+ true
+
+ end
+
+let init_known_elements_map module_list =
+ let c = new scan in
+ c#scan_module_list module_list
+
+
+(** The type to describe the names not found. *)
+type not_found_name =
+ NF_m of Name.t
+ | NF_mt of Name.t
+ | NF_mmt of Name.t
+ | NF_c of Name.t
+ | NF_ct of Name.t
+ | NF_cct of Name.t
+ | NF_ex of Name.t
+
+(** Functions to find and associate aliases elements. *)
+
+let rec associate_in_module module_list (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found) m =
+ let rec iter_kind (acc_b, acc_inc, acc_names) k =
+ match k with
+ Module_struct elements ->
+ List.fold_left
+ (associate_in_module_element module_list m.m_name)
+ (acc_b, acc_inc, acc_names)
+ elements
+
+ | Module_alias ma ->
+ (
+ match ma.ma_module with
+ Some _ ->
+ (acc_b, acc_inc, acc_names)
+ | None ->
+ let mmt_opt =
+ try Some (Mod (lookup_module ma.ma_name))
+ with Not_found ->
+ try Some (Modtype (lookup_module_type ma.ma_name))
+ with Not_found -> None
+ in
+ match mmt_opt with
+ None -> (acc_b, (Name.head m.m_name) :: acc_inc,
+ (* we don't want to output warning messages for
+ "sig ... end" or "struct ... end" modules not found *)
+ (if ma.ma_name = Odoc_messages.struct_end or
+ ma.ma_name = Odoc_messages.sig_end then
+ acc_names
+ else
+ (NF_mmt ma.ma_name) :: acc_names)
+ )
+ | Some mmt ->
+ ma.ma_module <- Some mmt ;
+ (true, acc_inc, acc_names)
+ )
+
+ | Module_functor (_, k) ->
+ iter_kind (acc_b, acc_inc, acc_names) k
+
+ | Module_with (tk, _) ->
+ associate_in_module_type module_list (acc_b, acc_inc, acc_names)
+ { mt_name = "" ; mt_info = None ; mt_type = None ;
+ mt_is_interface = false ; mt_file = ""; mt_kind = Some tk ;
+ mt_loc = Odoc_types.dummy_loc }
+
+ | Module_apply (k1, k2) ->
+ let (acc_b2, acc_inc2, acc_names2) = iter_kind (acc_b, acc_inc, acc_names) k1 in
+ iter_kind (acc_b2, acc_inc2, acc_names2) k2
+
+ | Module_constraint (k, tk) ->
+ let (acc_b2, acc_inc2, acc_names2) = iter_kind (acc_b, acc_inc, acc_names) k in
+ associate_in_module_type module_list (acc_b2, acc_inc2, acc_names2)
+ { mt_name = "" ; mt_info = None ; mt_type = None ;
+ mt_is_interface = false ; mt_file = "" ; mt_kind = Some tk ;
+ mt_loc = Odoc_types.dummy_loc }
+
+ | Module_typeof _ ->
+ (acc_b, acc_inc, acc_names)
+
+ | Module_unpack (code, mta) ->
+ begin
+ match mta.mta_module with
+ Some _ ->
+ (acc_b, acc_inc, acc_names)
+ | None ->
+ let mt_opt =
+ try Some (lookup_module_type mta.mta_name)
+ with Not_found -> None
+ in
+ match mt_opt with
+ None -> (acc_b, (Name.head m.m_name) :: acc_inc,
+ (* we don't want to output warning messages for
+ "sig ... end" or "struct ... end" modules not found *)
+ (if mta.mta_name = Odoc_messages.struct_end or
+ mta.mta_name = Odoc_messages.sig_end then
+ acc_names
+ else
+ (NF_mt mta.mta_name) :: acc_names)
+ )
+ | Some mt ->
+ mta.mta_module <- Some mt ;
+ (true, acc_inc, acc_names)
+ end
+ in
+ iter_kind (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found) m.m_kind
+
+and associate_in_module_type module_list (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found) mt =
+ let rec iter_kind (acc_b, acc_inc, acc_names) k =
+ match k with
+ Module_type_struct elements ->
+ List.fold_left
+ (associate_in_module_element module_list mt.mt_name)
+ (acc_b, acc_inc, acc_names)
+ elements
+
+ | Module_type_functor (_, k) ->
+ iter_kind (acc_b, acc_inc, acc_names) k
+
+ | Module_type_with (k, _) ->
+ iter_kind (acc_b, acc_inc, acc_names) k
+
+ | Module_type_alias mta ->
+ begin
+ match mta.mta_module with
+ Some _ ->
+ (acc_b, acc_inc, acc_names)
+ | None ->
+ let mt_opt =
+ try Some (lookup_module_type mta.mta_name)
+ with Not_found -> None
+ in
+ match mt_opt with
+ None -> (acc_b, (Name.head mt.mt_name) :: acc_inc,
+ (* we don't want to output warning messages for
+ "sig ... end" or "struct ... end" modules not found *)
+ (if mta.mta_name = Odoc_messages.struct_end or
+ mta.mta_name = Odoc_messages.sig_end then
+ acc_names
+ else
+ (NF_mt mta.mta_name) :: acc_names)
+ )
+ | Some mt ->
+ mta.mta_module <- Some mt ;
+ (true, acc_inc, acc_names)
+ end
+ | Module_type_typeof _ ->
+ (acc_b, acc_inc, acc_names)
+ in
+ match mt.mt_kind with
+ None -> (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found)
+ | Some k -> iter_kind (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found) k
+
+and associate_in_module_element module_list m_name (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found) element =
+ match element with
+ Element_module m -> associate_in_module module_list (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found) m
+ | Element_module_type mt -> associate_in_module_type module_list (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found) mt
+ | Element_included_module im ->
+ (
+ match im.im_module with
+ Some _ -> (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found)
+ | None ->
+ let mmt_opt =
+ try Some (Mod (lookup_module im.im_name))
+ with Not_found ->
+ try Some (Modtype (lookup_module_type im.im_name))
+ with Not_found -> None
+ in
+ match mmt_opt with
+ None -> (acc_b_modif, (Name.head m_name) :: acc_incomplete_top_module_names,
+ (* we don't want to output warning messages for
+ "sig ... end" or "struct ... end" modules not found *)
+ (if im.im_name = Odoc_messages.struct_end or
+ im.im_name = Odoc_messages.sig_end then
+ acc_names_not_found
+ else
+ (NF_mmt im.im_name) :: acc_names_not_found)
+ )
+ | Some mmt ->
+ im.im_module <- Some mmt ;
+ (true, acc_incomplete_top_module_names, acc_names_not_found)
+ )
+ | Element_class cl -> associate_in_class module_list (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found) cl
+ | Element_class_type ct -> associate_in_class_type module_list (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found) ct
+ | Element_value _ -> (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found)
+ | Element_exception ex ->
+ (
+ match ex.ex_alias with
+ None -> (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found)
+ | Some ea ->
+ match ea.ea_ex with
+ Some _ ->
+ (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found)
+ | None ->
+ let ex_opt =
+ try Some (lookup_exception ea.ea_name)
+ with Not_found -> None
+ in
+ match ex_opt with
+ None -> (acc_b_modif, (Name.head m_name) :: acc_incomplete_top_module_names, (NF_ex ea.ea_name) :: acc_names_not_found)
+ | Some e ->
+ ea.ea_ex <- Some e ;
+ (true, acc_incomplete_top_module_names, acc_names_not_found)
+ )
+ | Element_type _ -> (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found)
+ | Element_module_comment _ -> (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found)
+
+and associate_in_class module_list (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found) c =
+ let rec iter_kind (acc_b, acc_inc, acc_names) k =
+ match k with
+ Class_structure (inher_l, _) ->
+ let f (acc_b2, acc_inc2, acc_names2) ic =
+ match ic.ic_class with
+ Some _ -> (acc_b2, acc_inc2, acc_names2)
+ | None ->
+ let cct_opt =
+ try Some (Cl (lookup_class ic.ic_name))
+ with Not_found ->
+ try Some (Cltype (lookup_class_type ic.ic_name, []))
+ with Not_found -> None
+ in
+ match cct_opt with
+ None -> (acc_b2, (Name.head c.cl_name) :: acc_inc2,
+ (* we don't want to output warning messages for "object ... end" classes not found *)
+ (if ic.ic_name = Odoc_messages.object_end then acc_names2 else (NF_cct ic.ic_name) :: acc_names2))
+ | Some cct ->
+ ic.ic_class <- Some cct ;
+ (true, acc_inc2, acc_names2)
+ in
+ List.fold_left f (acc_b, acc_inc, acc_names) inher_l
+
+ | Class_apply capp ->
+ (
+ match capp.capp_class with
+ Some _ -> (acc_b, acc_inc, acc_names)
+ | None ->
+ let cl_opt =
+ try Some (lookup_class capp.capp_name)
+ with Not_found -> None
+ in
+ match cl_opt with
+ None -> (acc_b, (Name.head c.cl_name) :: acc_inc,
+ (* we don't want to output warning messages for "object ... end" classes not found *)
+ (if capp.capp_name = Odoc_messages.object_end then acc_names else (NF_c capp.capp_name) :: acc_names))
+ | Some c ->
+ capp.capp_class <- Some c ;
+ (true, acc_inc, acc_names)
+ )
+
+ | Class_constr cco ->
+ (
+ match cco.cco_class with
+ Some _ -> (acc_b, acc_inc, acc_names)
+ | None ->
+ let cl_opt =
+ try Some (lookup_class cco.cco_name)
+ with Not_found -> None
+ in
+ match cl_opt with
+ None ->
+ (
+ let clt_opt =
+ try Some (lookup_class_type cco.cco_name)
+ with Not_found -> None
+ in
+ match clt_opt with
+ None ->
+ (acc_b, (Name.head c.cl_name) :: acc_inc,
+ (* we don't want to output warning messages for "object ... end" classes not found *)
+ (if cco.cco_name = Odoc_messages.object_end then acc_names else (NF_cct cco.cco_name) :: acc_names))
+ | Some ct ->
+ cco.cco_class <- Some (Cltype (ct, [])) ;
+ (true, acc_inc, acc_names)
+ )
+ | Some c ->
+ cco.cco_class <- Some (Cl c) ;
+ (true, acc_inc, acc_names)
+ )
+ | Class_constraint (ckind, ctkind) ->
+ let (acc_b2, acc_inc2, acc_names2) = iter_kind (acc_b, acc_inc, acc_names) ckind in
+ associate_in_class_type module_list (acc_b2, acc_inc2, acc_names2)
+ { clt_name = "" ; clt_info = None ;
+ clt_type = c.cl_type ; (* should be ok *)
+ clt_type_parameters = [] ;
+ clt_virtual = false ;
+ clt_kind = ctkind ;
+ clt_loc = Odoc_types.dummy_loc }
+ in
+ iter_kind (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found) c.cl_kind
+
+and associate_in_class_type module_list (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found) ct =
+ let rec iter_kind (acc_b, acc_inc, acc_names) k =
+ match k with
+ Class_signature (inher_l, _) ->
+ let f (acc_b2, acc_inc2, acc_names2) ic =
+ match ic.ic_class with
+ Some _ -> (acc_b2, acc_inc2, acc_names2)
+ | None ->
+ let cct_opt =
+ try Some (Cltype (lookup_class_type ic.ic_name, []))
+ with Not_found ->
+ try Some (Cl (lookup_class ic.ic_name))
+ with Not_found -> None
+ in
+ match cct_opt with
+ None -> (acc_b2, (Name.head ct.clt_name) :: acc_inc2,
+ (* we don't want to output warning messages for "object ... end" class types not found *)
+ (if ic.ic_name = Odoc_messages.object_end then acc_names2 else (NF_cct ic.ic_name) :: acc_names2))
+ | Some cct ->
+ ic.ic_class <- Some cct ;
+ (true, acc_inc2, acc_names2)
+ in
+ List.fold_left f (acc_b, acc_inc, acc_names) inher_l
+
+ | Class_type cta ->
+ (
+ match cta.cta_class with
+ Some _ -> (acc_b, acc_inc, acc_names)
+ | None ->
+ let cct_opt =
+ try Some (Cltype (lookup_class_type cta.cta_name, []))
+ with Not_found ->
+ try Some (Cl (lookup_class cta.cta_name))
+ with Not_found -> None
+ in
+ match cct_opt with
+ None -> (acc_b, (Name.head ct.clt_name) :: acc_inc,
+ (* we don't want to output warning messages for "object ... end" class types not found *)
+ (if cta.cta_name = Odoc_messages.object_end then acc_names else (NF_cct cta.cta_name) :: acc_names))
+ | Some c ->
+ cta.cta_class <- Some c ;
+ (true, acc_inc, acc_names)
+ )
+ in
+ iter_kind (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found) ct.clt_kind
+
+(*************************************************************)
+(** Association of types to elements referenced in comments .*)
+
+let ao = Odoc_misc.apply_opt
+
+let not_found_of_kind kind name =
+ (match kind with
+ RK_module -> Odoc_messages.cross_module_not_found
+ | RK_module_type -> Odoc_messages.cross_module_type_not_found
+ | RK_class -> Odoc_messages.cross_class_not_found
+ | RK_class_type -> Odoc_messages.cross_class_type_not_found
+ | RK_value -> Odoc_messages.cross_value_not_found
+ | RK_type -> Odoc_messages.cross_type_not_found
+ | RK_exception -> Odoc_messages.cross_exception_not_found
+ | RK_attribute -> Odoc_messages.cross_attribute_not_found
+ | RK_method -> Odoc_messages.cross_method_not_found
+ | RK_section _ -> Odoc_messages.cross_section_not_found
+ ) name
+
+let rec assoc_comments_text_elements parent_name module_list t_ele =
+ match t_ele with
+ | Raw _
+ | Code _
+ | CodePre _
+ | Latex _
+ | Verbatim _ -> t_ele
+ | Bold t -> Bold (assoc_comments_text parent_name module_list t)
+ | Italic t -> Italic (assoc_comments_text parent_name module_list t)
+ | Center t -> Center (assoc_comments_text parent_name module_list t)
+ | Left t -> Left (assoc_comments_text parent_name module_list t)
+ | Right t -> Right (assoc_comments_text parent_name module_list t)
+ | Emphasize t -> Emphasize (assoc_comments_text parent_name module_list t)
+ | List l -> List (List.map (assoc_comments_text parent_name module_list) l)
+ | Enum l -> Enum (List.map (assoc_comments_text parent_name module_list) l)
+ | Newline -> Newline
+ | Block t -> Block (assoc_comments_text parent_name module_list t)
+ | Superscript t -> Superscript (assoc_comments_text parent_name module_list t)
+ | Subscript t -> Subscript (assoc_comments_text parent_name module_list t)
+ | Title (n, l_opt, t) -> Title (n, l_opt, (assoc_comments_text parent_name module_list t))
+ | Link (s, t) -> Link (s, (assoc_comments_text parent_name module_list t))
+ | Ref (initial_name, None, text_option) ->
+ (
+ let rec iter_parent ?parent_name name =
+ let name = Odoc_name.normalize_name name in
+ let res =
+ match get_known_elements name with
+ [] ->
+ (
+ try
+ let re = Str.regexp ("^"^(Str.quote name)^"$") in
+ let t = Odoc_search.find_section module_list re in
+ let v2 = (name, Some (RK_section t)) in
+ add_verified v2 ;
+ (name, Some (RK_section t))
+ with
+ Not_found ->
+ (name, None)
+ )
+ | ele :: _ ->
+ (* we look for the first element with this name *)
+ let (name, kind) =
+ match ele with
+ Odoc_search.Res_module m -> (m.m_name, RK_module)
+ | Odoc_search.Res_module_type mt -> (mt.mt_name, RK_module_type)
+ | Odoc_search.Res_class c -> (c.cl_name, RK_class)
+ | Odoc_search.Res_class_type ct -> (ct.clt_name, RK_class_type)
+ | Odoc_search.Res_value v -> (v.val_name, RK_value)
+ | Odoc_search.Res_type t -> (t.ty_name, RK_type)
+ | Odoc_search.Res_exception e -> (e.ex_name, RK_exception)
+ | Odoc_search.Res_attribute a -> (a.att_value.val_name, RK_attribute)
+ | Odoc_search.Res_method m -> (m.met_value.val_name, RK_method)
+ | Odoc_search.Res_section (_ ,t)-> assert false
+ in
+ add_verified (name, Some kind) ;
+ (name, Some kind)
+ in
+ match res with
+ | (name, Some k) -> Ref (name, Some k, text_option)
+ | (_, None) ->
+ match parent_name with
+ None ->
+ Odoc_global.pwarning (Odoc_messages.cross_element_not_found initial_name);
+ Ref (initial_name, None, text_option)
+ | Some p ->
+ let parent_name =
+ match Name.father p with
+ "" -> None
+ | s -> Some s
+ in
+ iter_parent ?parent_name (Name.concat p initial_name)
+ in
+ iter_parent ~parent_name initial_name
+ )
+ | Ref (initial_name, Some kind, text_option) ->
+ (
+ let rec iter_parent ?parent_name name =
+ let v = (name, Some kind) in
+ if was_verified v then
+ Ref (name, Some kind, text_option)
+ else
+ let res =
+ match kind with
+ | RK_section _ ->
+ (
+ (** we just verify that we find an element of this kind with this name *)
+ try
+ let re = Str.regexp ("^"^(Str.quote name)^"$") in
+ let t = Odoc_search.find_section module_list re in
+ let v2 = (name, Some (RK_section t)) in
+ add_verified v2 ;
+ (name, Some (RK_section t))
+ with
+ Not_found ->
+ (name, None)
+ )
+ | _ ->
+ let f =
+ match kind with
+ RK_module -> module_exists
+ | RK_module_type -> module_type_exists
+ | RK_class -> class_exists
+ | RK_class_type -> class_type_exists
+ | RK_value -> value_exists
+ | RK_type -> type_exists
+ | RK_exception -> exception_exists
+ | RK_attribute -> attribute_exists
+ | RK_method -> method_exists
+ | RK_section _ -> assert false
+ in
+ if f name then
+ (
+ add_verified v ;
+ (name, Some kind)
+ )
+ else
+ (name, None)
+ in
+ match res with
+ | (name, Some k) -> Ref (name, Some k, text_option)
+ | (_, None) ->
+ match parent_name with
+ None ->
+ Odoc_global.pwarning (not_found_of_kind kind initial_name);
+ Ref (initial_name, None, text_option)
+ | Some p ->
+ let parent_name =
+ match Name.father p with
+ "" -> None
+ | s -> Some s
+ in
+ iter_parent ?parent_name (Name.concat p initial_name)
+ in
+ iter_parent ~parent_name initial_name
+ )
+ | Module_list l ->
+ Module_list l
+ | Index_list ->
+ Index_list
+ | Custom (s,t) -> Custom (s, (assoc_comments_text parent_name module_list t))
+ | Target (target, code) -> Target (target, code)
+
+and assoc_comments_text parent_name module_list text =
+ List.map (assoc_comments_text_elements parent_name module_list) text
+
+and assoc_comments_info parent_name module_list i =
+ let ft = assoc_comments_text parent_name module_list in
+ {
+ i with
+ i_desc = ao ft i.i_desc ;
+ i_sees = List.map (fun (sr, t) -> (sr, ft t)) i.i_sees;
+ i_deprecated = ao ft i.i_deprecated ;
+ i_params = List.map (fun (name, t) -> (name, ft t)) i.i_params;
+ i_raised_exceptions = List.map (fun (name, t) -> (name, ft t)) i.i_raised_exceptions;
+ i_return_value = ao ft i.i_return_value ;
+ i_custom = List.map (fun (tag, t) -> (tag, ft t)) i.i_custom ;
+ }
+
+
+let rec assoc_comments_module_element parent_name module_list m_ele =
+ match m_ele with
+ Element_module m ->
+ Element_module (assoc_comments_module module_list m)
+ | Element_module_type mt ->
+ Element_module_type (assoc_comments_module_type module_list mt)
+ | Element_included_module _ ->
+ m_ele (* don't go down into the aliases *)
+ | Element_class c ->
+ Element_class (assoc_comments_class module_list c)
+ | Element_class_type ct ->
+ Element_class_type (assoc_comments_class_type module_list ct)
+ | Element_value v ->
+ Element_value (assoc_comments_value module_list v)
+ | Element_exception e ->
+ Element_exception (assoc_comments_exception module_list e)
+ | Element_type t ->
+ Element_type (assoc_comments_type module_list t)
+ | Element_module_comment t ->
+ Element_module_comment (assoc_comments_text parent_name module_list t)
+
+and assoc_comments_class_element parent_name module_list c_ele =
+ match c_ele with
+ Class_attribute a ->
+ Class_attribute (assoc_comments_attribute module_list a)
+ | Class_method m ->
+ Class_method (assoc_comments_method module_list m)
+ | Class_comment t ->
+ Class_comment (assoc_comments_text parent_name module_list t)
+
+and assoc_comments_module_kind parent_name module_list mk =
+ match mk with
+ | Module_struct eles ->
+ Module_struct
+ (List.map (assoc_comments_module_element parent_name module_list) eles)
+ | Module_alias _
+ | Module_functor _ ->
+ mk
+ | Module_apply (mk1, mk2) ->
+ Module_apply (assoc_comments_module_kind parent_name module_list mk1,
+ assoc_comments_module_kind parent_name module_list mk2)
+ | Module_with (mtk, s) ->
+ Module_with (assoc_comments_module_type_kind parent_name module_list mtk, s)
+ | Module_constraint (mk1, mtk) ->
+ Module_constraint
+ (assoc_comments_module_kind parent_name module_list mk1,
+ assoc_comments_module_type_kind parent_name module_list mtk)
+ | Module_typeof _ -> mk
+ | Module_unpack _ -> mk
+
+and assoc_comments_module_type_kind parent_name module_list mtk =
+ match mtk with
+ | Module_type_struct eles ->
+ Module_type_struct
+ (List.map (assoc_comments_module_element parent_name module_list) eles)
+ | Module_type_functor (params, mtk1) ->
+ Module_type_functor
+ (params, assoc_comments_module_type_kind parent_name module_list mtk1)
+ | Module_type_alias _ ->
+ mtk
+ | Module_type_with (mtk1, s) ->
+ Module_type_with
+ (assoc_comments_module_type_kind parent_name module_list mtk1, s)
+ | Module_type_typeof _ -> mtk
+
+and assoc_comments_class_kind parent_name module_list ck =
+ match ck with
+ Class_structure (inher, eles) ->
+ let inher2 =
+ List.map
+ (fun ic ->
+ { ic with
+ ic_text = ao (assoc_comments_text parent_name module_list) ic.ic_text })
+ inher
+ in
+ Class_structure
+ (inher2, List.map (assoc_comments_class_element parent_name module_list) eles)
+
+ | Class_apply _
+ | Class_constr _ -> ck
+ | Class_constraint (ck1, ctk) ->
+ Class_constraint (assoc_comments_class_kind parent_name module_list ck1,
+ assoc_comments_class_type_kind parent_name module_list ctk)
+
+and assoc_comments_class_type_kind parent_name module_list ctk =
+ match ctk with
+ Class_signature (inher, eles) ->
+ let inher2 =
+ List.map
+ (fun ic -> { ic with
+ ic_text = ao (assoc_comments_text parent_name module_list) ic.ic_text })
+ inher
+ in
+ Class_signature (inher2, List.map (assoc_comments_class_element parent_name module_list) eles)
+
+ | Class_type _ -> ctk
+
+
+and assoc_comments_module module_list m =
+ m.m_info <- ao (assoc_comments_info m.m_name module_list) m.m_info ;
+ m.m_kind <- assoc_comments_module_kind m.m_name module_list m.m_kind ;
+ m
+
+and assoc_comments_module_type module_list mt =
+ mt.mt_info <- ao (assoc_comments_info mt.mt_name module_list) mt.mt_info ;
+ mt.mt_kind <- ao (assoc_comments_module_type_kind mt.mt_name module_list) mt.mt_kind ;
+ mt
+
+and assoc_comments_class module_list c =
+ c.cl_info <- ao (assoc_comments_info c.cl_name module_list) c.cl_info ;
+ c.cl_kind <- assoc_comments_class_kind c.cl_name module_list c.cl_kind ;
+ assoc_comments_parameter_list c.cl_name module_list c.cl_parameters;
+ c
+
+and assoc_comments_class_type module_list ct =
+ ct.clt_info <- ao (assoc_comments_info ct.clt_name module_list) ct.clt_info ;
+ ct.clt_kind <- assoc_comments_class_type_kind ct.clt_name module_list ct.clt_kind ;
+ ct
+
+and assoc_comments_parameter parent_name module_list p =
+ match p with
+ Simple_name sn ->
+ sn.sn_text <- ao (assoc_comments_text parent_name module_list) sn.sn_text
+ | Tuple (l, t) ->
+ List.iter (assoc_comments_parameter parent_name module_list) l
+
+and assoc_comments_parameter_list parent_name module_list pl =
+ List.iter (assoc_comments_parameter parent_name module_list) pl
+
+and assoc_comments_value module_list v =
+ let parent = Name.father v.val_name in
+ v.val_info <- ao (assoc_comments_info parent module_list) v.val_info ;
+ assoc_comments_parameter_list parent module_list v.val_parameters;
+ v
+
+and assoc_comments_exception module_list e =
+ let parent = Name.father e.ex_name in
+ e.ex_info <- ao (assoc_comments_info parent module_list) e.ex_info ;
+ e
+
+and assoc_comments_type module_list t =
+ let parent = Name.father t.ty_name in
+ t.ty_info <- ao (assoc_comments_info parent module_list) t.ty_info ;
+ (match t.ty_kind with
+ Type_abstract -> ()
+ | Type_variant vl ->
+ List.iter
+ (fun vc -> vc.vc_text <- ao (assoc_comments_text parent module_list) vc.vc_text)
+ vl
+ | Type_record fl ->
+ List.iter
+ (fun rf -> rf.rf_text <- ao (assoc_comments_text parent module_list) rf.rf_text)
+ fl
+ );
+ t
+
+and assoc_comments_attribute module_list a =
+ let _ = assoc_comments_value module_list a.att_value in
+ a
+
+and assoc_comments_method module_list m =
+ let parent_name = Name.father m.met_value.val_name in
+ let _ = assoc_comments_value module_list m.met_value in
+ assoc_comments_parameter_list parent_name module_list m.met_value.val_parameters;
+ m
+
+
+let associate_type_of_elements_in_comments module_list =
+ List.map (assoc_comments_module module_list) module_list
+
+
+(***********************************************************)
+(** The function which performs all the cross referencing. *)
+let associate module_list =
+ get_alias_names module_list ;
+ init_known_elements_map module_list;
+ let rec remove_doubles acc = function
+ [] -> acc
+ | h :: q ->
+ if List.mem h acc then remove_doubles acc q
+ else remove_doubles (h :: acc) q
+ in
+ let rec iter incomplete_modules =
+ let (b_modif, remaining_inc_modules, acc_names_not_found) =
+ List.fold_left (associate_in_module module_list) (false, [], []) incomplete_modules
+ in
+ let remaining_no_doubles = remove_doubles [] remaining_inc_modules in
+ let remaining_modules = List.filter
+ (fun m -> List.mem m.m_name remaining_no_doubles)
+ incomplete_modules
+ in
+ if b_modif then
+ (* we may be able to associate something else *)
+ iter remaining_modules
+ else
+ (* nothing changed, we won't be able to associate any more *)
+ acc_names_not_found
+ in
+ let names_not_found = iter module_list in
+ (
+ match names_not_found with
+ [] ->
+ ()
+ | l ->
+ List.iter
+ (fun nf ->
+ Odoc_global.pwarning
+ (
+ match nf with
+ NF_m n -> Odoc_messages.cross_module_not_found n
+ | NF_mt n -> Odoc_messages.cross_module_type_not_found n
+ | NF_mmt n -> Odoc_messages.cross_module_or_module_type_not_found n
+ | NF_c n -> Odoc_messages.cross_class_not_found n
+ | NF_ct n -> Odoc_messages.cross_class_type_not_found n
+ | NF_cct n -> Odoc_messages.cross_class_or_class_type_not_found n
+ | NF_ex n -> Odoc_messages.cross_exception_not_found n
+ );
+ )
+ l
+ ) ;
+
+ (* Find a type for each name of element which is referenced in comments. *)
+ ignore (associate_type_of_elements_in_comments module_list)