Add copyright notices and new function String.chomp
[ocaml.git] / ocamldoc / odoc_module.ml
blob3352bd8df1c86f517f3d3fee0138a4475df900c3
1 (***********************************************************************)
2 (* OCamldoc *)
3 (* *)
4 (* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
5 (* *)
6 (* Copyright 2001 Institut National de Recherche en Informatique et *)
7 (* en Automatique. All rights reserved. This file is distributed *)
8 (* under the terms of the Q Public License version 1.0. *)
9 (* *)
10 (***********************************************************************)
12 (* $Id$ *)
14 (** Representation and manipulation of modules and module types. *)
16 let print_DEBUG s = print_string s ; print_newline ()
18 module Name = Odoc_name
20 (** To keep the order of elements in a module. *)
21 type module_element =
22 Element_module of t_module
23 | Element_module_type of t_module_type
24 | Element_included_module of included_module
25 | Element_class of Odoc_class.t_class
26 | Element_class_type of Odoc_class.t_class_type
27 | Element_value of Odoc_value.t_value
28 | Element_exception of Odoc_exception.t_exception
29 | Element_type of Odoc_type.t_type
30 | Element_module_comment of Odoc_types.text
32 (** Used where we can reference t_module or t_module_type *)
33 and mmt =
34 | Mod of t_module
35 | Modtype of t_module_type
37 and included_module = {
38 im_name : Name.t ; (** the name of the included module *)
39 mutable im_module : mmt option ; (** the included module or module type *)
40 mutable im_info : Odoc_types.info option ; (** comment associated to the includ directive *)
43 and module_alias = {
44 ma_name : Name.t ;
45 mutable ma_module : mmt option ; (** the real module or module type if we could associate it *)
48 and module_parameter = {
49 mp_name : string ; (** the name *)
50 mp_type : Types.module_type ; (** the type *)
51 mp_type_code : string ; (** the original code *)
52 mp_kind : module_type_kind ; (** the way the parameter was built *)
55 (** Different kinds of module. *)
56 and module_kind =
57 | Module_struct of module_element list
58 | Module_alias of module_alias (** complete name and corresponding module if we found it *)
59 | Module_functor of module_parameter * module_kind
60 | Module_apply of module_kind * module_kind
61 | Module_with of module_type_kind * string
62 | Module_constraint of module_kind * module_type_kind
64 (** Representation of a module. *)
65 and t_module = {
66 m_name : Name.t ;
67 mutable m_type : Types.module_type ;
68 mutable m_info : Odoc_types.info option ;
69 m_is_interface : bool ; (** true for modules read from interface files *)
70 m_file : string ; (** the file the module is defined in. *)
71 mutable m_kind : module_kind ;
72 mutable m_loc : Odoc_types.location ;
73 mutable m_top_deps : Name.t list ; (** The toplevels module names this module depends on. *)
74 mutable m_code : string option ; (** The whole code of the module *)
75 mutable m_code_intf : string option ; (** The whole code of the interface of the module *)
76 m_text_only : bool ; (** [true] if the module comes from a text file *)
79 and module_type_alias = {
80 mta_name : Name.t ;
81 mutable mta_module : t_module_type option ; (** the real module type if we could associate it *)
84 (** Different kinds of module type. *)
85 and module_type_kind =
86 | Module_type_struct of module_element list
87 | Module_type_functor of module_parameter * module_type_kind
88 | Module_type_alias of module_type_alias (** complete name and corresponding module type if we found it *)
89 | Module_type_with of module_type_kind * string (** the module type kind and the code of the with constraint *)
91 (** Representation of a module type. *)
92 and t_module_type = {
93 mt_name : Name.t ;
94 mutable mt_info : Odoc_types.info option ;
95 mutable mt_type : Types.module_type option ; (** [None] = abstract module type *)
96 mt_is_interface : bool ; (** true for modules read from interface files *)
97 mt_file : string ; (** the file the module type is defined in. *)
98 mutable mt_kind : module_type_kind option ; (** [None] = abstract module type if mt_type = None ;
99 Always [None] when the module type was extracted from the implementation file. *)
100 mutable mt_loc : Odoc_types.location ;
104 (** {2 Functions} *)
106 (** Returns the list of values from a list of module_element. *)
107 let values l =
108 List.fold_left
109 (fun acc -> fun ele ->
110 match ele with
111 Element_value v -> acc @ [v]
112 | _ -> acc
117 (** Returns the list of types from a list of module_element. *)
118 let types l =
119 List.fold_left
120 (fun acc -> fun ele ->
121 match ele with
122 Element_type t -> acc @ [t]
123 | _ -> acc
128 (** Returns the list of exceptions from a list of module_element. *)
129 let exceptions l =
130 List.fold_left
131 (fun acc -> fun ele ->
132 match ele with
133 Element_exception e -> acc @ [e]
134 | _ -> acc
139 (** Returns the list of classes from a list of module_element. *)
140 let classes l =
141 List.fold_left
142 (fun acc -> fun ele ->
143 match ele with
144 Element_class c -> acc @ [c]
145 | _ -> acc
150 (** Returns the list of class types from a list of module_element. *)
151 let class_types l =
152 List.fold_left
153 (fun acc -> fun ele ->
154 match ele with
155 Element_class_type ct -> acc @ [ct]
156 | _ -> acc
161 (** Returns the list of modules from a list of module_element. *)
162 let modules l =
163 List.fold_left
164 (fun acc -> fun ele ->
165 match ele with
166 Element_module m -> acc @ [m]
167 | _ -> acc
172 (** Returns the list of module types from a list of module_element. *)
173 let mod_types l =
174 List.fold_left
175 (fun acc -> fun ele ->
176 match ele with
177 Element_module_type mt -> acc @ [mt]
178 | _ -> acc
183 (** Returns the list of module comment from a list of module_element. *)
184 let comments l =
185 List.fold_left
186 (fun acc -> fun ele ->
187 match ele with
188 Element_module_comment t -> acc @ [t]
189 | _ -> acc
194 (** Returns the list of included modules from a list of module_element. *)
195 let included_modules l =
196 List.fold_left
197 (fun acc -> fun ele ->
198 match ele with
199 Element_included_module m -> acc @ [m]
200 | _ -> acc
205 (** Returns the list of elements of a module.
206 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
207 let rec module_elements ?(trans=true) m =
208 let rec iter_kind = function
209 Module_struct l ->
210 print_DEBUG "Odoc_module.module_element: Module_struct";
212 | Module_alias ma ->
213 print_DEBUG "Odoc_module.module_element: Module_alias";
214 if trans then
215 match ma.ma_module with
216 None -> []
217 | Some (Mod m) -> module_elements m
218 | Some (Modtype mt) -> module_type_elements mt
219 else
221 | Module_functor (_, k)
222 | Module_apply (k, _) ->
223 print_DEBUG "Odoc_module.module_element: Module_functor ou Module_apply";
224 iter_kind k
225 | Module_with (tk,_) ->
226 print_DEBUG "Odoc_module.module_element: Module_with";
227 module_type_elements ~trans: trans
228 { mt_name = "" ; mt_info = None ; mt_type = None ;
229 mt_is_interface = false ; mt_file = "" ; mt_kind = Some tk ;
230 mt_loc = Odoc_types.dummy_loc ;
232 | Module_constraint (k, tk) ->
233 print_DEBUG "Odoc_module.module_element: Module_constraint";
234 (* A VOIR : utiliser k ou tk ? *)
235 module_elements ~trans: trans
236 { m_name = "" ;
237 m_info = None ;
238 m_type = Types.Tmty_signature [] ;
239 m_is_interface = false ; m_file = "" ; m_kind = k ;
240 m_loc = Odoc_types.dummy_loc ;
241 m_top_deps = [] ;
242 m_code = None ;
243 m_code_intf = None ;
244 m_text_only = false ;
247 module_type_elements ~trans: trans
248 { mt_name = "" ; mt_info = None ; mt_type = None ;
249 mt_is_interface = false ; mt_file = "" ; mt_kind = Some tk ;
250 mt_loc = Odoc_types.dummy_loc }
253 iter_kind m.m_kind
255 (** Returns the list of elements of a module type.
256 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
257 and module_type_elements ?(trans=true) mt =
258 let rec iter_kind = function
259 | None -> []
260 | Some (Module_type_struct l) -> l
261 | Some (Module_type_functor (_, k)) -> iter_kind (Some k)
262 | Some (Module_type_with (k, _)) ->
263 if trans then
264 iter_kind (Some k)
265 else
267 | Some (Module_type_alias mta) ->
268 if trans then
269 match mta.mta_module with
270 None -> []
271 | Some mt -> module_type_elements mt
272 else
275 iter_kind mt.mt_kind
277 (** Returns the list of values of a module.
278 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
279 let module_values ?(trans=true) m = values (module_elements ~trans m)
281 (** Returns the list of functional values of a module.
282 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
283 let module_functions ?(trans=true) m =
284 List.filter
285 (fun v -> Odoc_value.is_function v)
286 (values (module_elements ~trans m))
288 (** Returns the list of non-functional values of a module.
289 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
290 let module_simple_values ?(trans=true) m =
291 List.filter
292 (fun v -> not (Odoc_value.is_function v))
293 (values (module_elements ~trans m))
295 (** Returns the list of types of a module.
296 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
297 let module_types ?(trans=true) m = types (module_elements ~trans m)
299 (** Returns the list of excptions of a module.
300 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
301 let module_exceptions ?(trans=true) m = exceptions (module_elements ~trans m)
303 (** Returns the list of classes of a module.
304 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
305 let module_classes ?(trans=true) m = classes (module_elements ~trans m)
307 (** Returns the list of class types of a module.
308 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
309 let module_class_types ?(trans=true) m = class_types (module_elements ~trans m)
311 (** Returns the list of modules of a module.
312 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
313 let module_modules ?(trans=true) m = modules (module_elements ~trans m)
315 (** Returns the list of module types of a module.
316 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
317 let module_module_types ?(trans=true) m = mod_types (module_elements ~trans m)
319 (** Returns the list of included module of a module.
320 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
321 let module_included_modules ?(trans=true) m = included_modules (module_elements ~trans m)
323 (** Returns the list of comments of a module.
324 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
325 let module_comments ?(trans=true) m = comments (module_elements ~trans m)
327 (** Access to the parameters, for a functor type.
328 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
329 let rec module_type_parameters ?(trans=true) mt =
330 let rec iter k =
331 match k with
332 Some (Module_type_functor (p, k2)) ->
333 let param =
334 (* we create the couple (parameter, description opt), using
335 the description of the parameter if we can find it in the comment.*)
336 match mt.mt_info with
337 None -> (p, None)
338 | Some i ->
340 let d = List.assoc p.mp_name i.Odoc_types.i_params in
341 (p, Some d)
342 with
343 Not_found ->
344 (p, None)
346 param :: (iter (Some k2))
347 | Some (Module_type_alias mta) ->
348 if trans then
349 match mta.mta_module with
350 None -> []
351 | Some mt2 -> module_type_parameters ~trans mt2
352 else
354 | Some (Module_type_with (k, _)) ->
355 if trans then
356 iter (Some k)
357 else
359 | Some (Module_type_struct _) ->
361 | None ->
364 iter mt.mt_kind
366 (** Access to the parameters, for a functor.
367 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
368 and module_parameters ?(trans=true) m =
369 let rec iter = function
370 Module_functor (p, k) ->
371 let param =
372 (* we create the couple (parameter, description opt), using
373 the description of the parameter if we can find it in the comment.*)
374 match m.m_info with
375 None ->(p, None)
376 | Some i ->
378 let d = List.assoc p.mp_name i.Odoc_types.i_params in
379 (p, Some d)
380 with
381 Not_found ->
382 (p, None)
384 param :: (iter k)
386 | Module_alias ma ->
387 if trans then
388 match ma.ma_module with
389 None -> []
390 | Some (Mod m) -> module_parameters ~trans m
391 | Some (Modtype mt) -> module_type_parameters ~trans mt
392 else
394 | Module_constraint (k, tk) ->
395 module_type_parameters ~trans: trans
396 { mt_name = "" ; mt_info = None ; mt_type = None ;
397 mt_is_interface = false ; mt_file = "" ; mt_kind = Some tk ;
398 mt_loc = Odoc_types.dummy_loc }
399 | Module_struct _
400 | Module_apply _
401 | Module_with _ ->
404 iter m.m_kind
406 (** access to all submodules and sudmobules of submodules ... of the given module.
407 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
408 let rec module_all_submodules ?(trans=true) m =
409 let l = module_modules ~trans m in
410 List.fold_left
411 (fun acc -> fun m -> acc @ (module_all_submodules ~trans m))
415 (** The module type is a functor if is defined as a functor or if it is an alias for a functor. *)
416 let rec module_type_is_functor mt =
417 let rec iter k =
418 match k with
419 Some (Module_type_functor _) -> true
420 | Some (Module_type_alias mta) ->
422 match mta.mta_module with
423 None -> false
424 | Some mtyp -> module_type_is_functor mtyp
426 | Some (Module_type_with (k, _)) ->
427 iter (Some k)
428 | Some (Module_type_struct _)
429 | None -> false
431 iter mt.mt_kind
433 (** The module is a functor if is defined as a functor or if it is an alias for a functor. *)
434 let module_is_functor m =
435 let rec iter = function
436 Module_functor _ -> true
437 | Module_alias ma ->
439 match ma.ma_module with
440 None -> false
441 | Some (Mod mo) -> iter mo.m_kind
442 | Some (Modtype mt) -> module_type_is_functor mt
444 | Module_constraint (k, _) ->
445 iter k
446 | _ -> false
448 iter m.m_kind
450 (** Returns the list of values of a module type.
451 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
452 let module_type_values ?(trans=true) m = values (module_type_elements ~trans m)
454 (** Returns the list of types of a module.
455 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
456 let module_type_types ?(trans=true) m = types (module_type_elements ~trans m)
458 (** Returns the list of excptions of a module.
459 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
460 let module_type_exceptions ?(trans=true) m = exceptions (module_type_elements ~trans m)
462 (** Returns the list of classes of a module.
463 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
464 let module_type_classes ?(trans=true) m = classes (module_type_elements ~trans m)
466 (** Returns the list of class types of a module.
467 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
468 let module_type_class_types ?(trans=true) m = class_types (module_type_elements ~trans m)
470 (** Returns the list of modules of a module.
471 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
472 let module_type_modules ?(trans=true) m = modules (module_type_elements ~trans m)
474 (** Returns the list of module types of a module.
475 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
476 let module_type_module_types ?(trans=true) m = mod_types (module_type_elements ~trans m)
478 (** Returns the list of included module of a module.
479 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
480 let module_type_included_modules ?(trans=true) m = included_modules (module_type_elements ~trans m)
482 (** Returns the list of comments of a module.
483 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
484 let module_type_comments ?(trans=true) m = comments (module_type_elements ~trans m)
486 (** Returns the list of functional values of a module type.
487 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
488 let module_type_functions ?(trans=true) mt =
489 List.filter
490 (fun v -> Odoc_value.is_function v)
491 (values (module_type_elements ~trans mt))
493 (** Returns the list of non-functional values of a module type.
494 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
495 let module_type_simple_values ?(trans=true) mt =
496 List.filter
497 (fun v -> not (Odoc_value.is_function v))
498 (values (module_type_elements ~trans mt))
500 (** {2 Functions for modules and module types} *)
502 (** The list of classes defined in this module and all its modules, functors, ....
503 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
504 let rec module_all_classes ?(trans=true) m =
505 List.fold_left
506 (fun acc -> fun m -> acc @ (module_all_classes ~trans m))
508 List.fold_left
509 (fun acc -> fun mtyp -> acc @ (module_type_all_classes ~trans mtyp))
510 (module_classes ~trans m)
511 (module_module_types ~trans m)
513 (module_modules ~trans m)
515 (** The list of classes defined in this module type and all its modules, functors, ....
516 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
517 and module_type_all_classes ?(trans=true) mt =
518 List.fold_left
519 (fun acc -> fun m -> acc @ (module_all_classes ~trans m))
521 List.fold_left
522 (fun acc -> fun mtyp -> acc @ (module_type_all_classes ~trans mtyp))
523 (module_type_classes ~trans mt)
524 (module_type_module_types ~trans mt)
526 (module_type_modules ~trans mt)