1 (***********************************************************************)
4 (* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
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. *)
10 (***********************************************************************)
14 (** Merge of information from [.ml] and [.mli] for a module.*)
18 module Name
= Odoc_name
26 (** Merge two Odoctypes.info struture, completing the information of
27 the first one with the information in the second one.
28 The merge treatment depends on a given merge_option list.
29 @return the new info structure.*)
30 let merge_info merge_options
(m1
: info
) (m2
: info
) =
32 match m1
.i_desc
, m2
.i_desc
with
35 | Some d
, None
-> Some d
37 if List.mem Merge_description merge_options
then
38 Some
(d1
@ (Newline
:: d2
))
43 match m1
.i_authors
, m2
.i_authors
with
48 if List.mem Merge_author merge_options
then
54 match m1
.i_version
, m2
.i_version
with
57 | None
, Some v
-> Some v
59 if List.mem Merge_version merge_options
then
65 match m1
.i_sees
, m2
.i_sees
with
70 if List.mem Merge_see merge_options
then
76 match m1
.i_since
, m2
.i_since
with
79 | None
, Some v
-> Some v
81 if List.mem Merge_since merge_options
then
87 match m1
.i_deprecated
, m2
.i_deprecated
with
90 | Some t
, None
-> Some t
92 if List.mem Merge_deprecated merge_options
then
93 Some
(t1
@ (Newline
:: t2
))
98 match m1
.i_params
, m2
.i_params
with
103 if List.mem Merge_param merge_options
then
105 let l_in_m1_and_m2, l_in_m2_only
= List.partition
106 (fun (param2
, _
) -> List.mem_assoc param2 l1
)
109 let rec iter = function
111 | (param2
, desc2
) :: q
->
112 let desc1 = List.assoc param2 l1
in
113 (param2
, desc1 @ (Newline
:: desc2
)) :: (iter q
)
115 let l1_completed = iter l_in_m1_and_m2 in
116 l1_completed @ l_in_m2_only
121 let new_raised_exceptions =
122 match m1
.i_raised_exceptions
, m2
.i_raised_exceptions
with
127 if List.mem Merge_raised_exception merge_options
then
129 let l_in_m1_and_m2, l_in_m2_only
= List.partition
130 (fun (exc2
, _
) -> List.mem_assoc exc2 l1
)
133 let rec iter = function
135 | (exc2
, desc2
) :: q
->
136 let desc1 = List.assoc exc2 l1
in
137 (exc2
, desc1 @ (Newline
:: desc2
)) :: (iter q
)
139 let l1_completed = iter l_in_m1_and_m2 in
140 l1_completed @ l_in_m2_only
146 match m1
.i_return_value
, m2
.i_return_value
with
149 | Some t
, None
-> Some t
150 | Some t1
, Some t2
->
151 if List.mem Merge_return_value merge_options
then
152 Some
(t1
@ (Newline
:: t2
))
157 match m1
.i_custom
, m2
.i_custom
with
162 if List.mem Merge_custom merge_options
then
168 Odoc_types.i_desc
= new_desc_opt ;
169 Odoc_types.i_authors
= new_authors ;
170 Odoc_types.i_version
= new_version ;
171 Odoc_types.i_sees
= new_sees ;
172 Odoc_types.i_since
= new_since ;
173 Odoc_types.i_deprecated
= new_dep ;
174 Odoc_types.i_params
= new_params ;
175 Odoc_types.i_raised_exceptions
= new_raised_exceptions ;
176 Odoc_types.i_return_value
= new_rv ;
177 Odoc_types.i_custom
= new_custom ;
180 (** Merge of two optional info structures. *)
181 let merge_info_opt merge_options mli_opt ml_opt
=
182 match mli_opt
, ml_opt
with
183 None
, Some i
-> Some i
184 | Some i
, None
-> Some i
186 | Some i1
, Some i2
-> Some
(merge_info merge_options i1 i2
)
188 (** merge of two t_type, one for a .mli, another for the .ml.
189 The .mli type is completed with the information in the .ml type. *)
190 let merge_types merge_options mli ml
=
191 mli
.ty_info
<- merge_info_opt merge_options mli
.ty_info ml
.ty_info
;
192 mli
.ty_loc
<- { mli
.ty_loc
with loc_impl
= ml
.ty_loc
.loc_impl
} ;
193 mli
.ty_code
<- (match mli
.ty_code
with None
-> ml
.ty_code
| _
-> mli
.ty_code
) ;
195 match mli
.ty_kind
, ml
.ty_kind
with
199 | Type_variant
(l1
, _
), Type_variant
(l2
, _
) ->
202 let cons2 = List.find
203 (fun c2
-> c2
.vc_name
= cons
.vc_name
)
207 match cons
.vc_text
, cons2.vc_text
with
210 | None
, Some d
-> Some d
211 | Some d1
, Some d2
->
212 if List.mem Merge_description merge_options
then
217 cons
.vc_text
<- new_desc
220 if !Odoc_args.inverse_merge_ml_mli
then
223 raise
(Failure
(Odoc_messages.different_types mli
.ty_name
))
227 | Type_record
(l1
, _
), Type_record
(l2
, _
) ->
230 let record2= List.find
231 (fun r
-> r
.rf_name
= record
.rf_name
)
235 match record
.rf_text
, record2.rf_text
with
238 | None
, Some d
-> Some d
239 | Some d1
, Some d2
->
240 if List.mem Merge_description merge_options
then
245 record
.rf_text
<- new_desc
248 if !Odoc_args.inverse_merge_ml_mli
then
251 raise
(Failure
(Odoc_messages.different_types mli
.ty_name
))
256 if !Odoc_args.inverse_merge_ml_mli
then
259 raise
(Failure
(Odoc_messages.different_types mli
.ty_name
))
261 (** Merge of two param_info, one from a .mli, one from a .ml.
262 The text fields are not handled but will be recreated from the
263 i_params field of the info structure.
264 Here, if a parameter in the .mli has no name, we take the one
265 from the .ml. When two parameters have two different forms,
266 we take the one from the .mli. *)
267 let rec merge_param_info pi_mli pi_ml
=
268 match (pi_mli
, pi_ml
) with
269 (Simple_name sn_mli
, Simple_name sn_ml
) ->
270 if sn_mli
.sn_name
= "" then
271 Simple_name
{ sn_mli
with sn_name
= sn_ml
.sn_name
}
274 | (Simple_name _
, Tuple _
) ->
276 | (Tuple
(_
, t_mli
), Simple_name sn_ml
) ->
277 (* if we're here, then the tuple in the .mli has no parameter names ;
278 then we take the name of the parameter of the .ml and the type of the .mli. *)
279 Simple_name
{ sn_ml
with sn_type
= t_mli
}
281 | (Tuple
(l_mli
, t_mli
), Tuple
(l_ml
, _
)) ->
282 (* if the two tuples have different lengths
283 (which should not occurs), we return the pi_mli,
284 without further investigation.*)
285 if (List.length l_mli
) <> (List.length l_ml
) then
288 let new_l = List.map2
merge_param_info l_mli l_ml
in
291 (** Merge of the parameters of two functions/methods/classes, one for a .mli, another for a .ml.
292 The prameters in the .mli are completed by the name in the .ml.*)
293 let rec merge_parameters param_mli param_ml
=
294 match (param_mli
, param_ml
) with
296 | (l
, []) | ([], l
) -> l
297 | ((pi_mli
:: li
), (pi_ml
:: l
)) ->
298 (merge_param_info pi_mli pi_ml
) :: merge_parameters li l
300 (** Merge of two t_class, one for a .mli, another for the .ml.
301 The .mli class is completed with the information in the .ml class. *)
302 let merge_classes merge_options mli ml
=
303 mli
.cl_info
<- merge_info_opt merge_options mli
.cl_info ml
.cl_info
;
304 mli
.cl_loc
<- { mli
.cl_loc
with loc_impl
= ml
.cl_loc
.loc_impl
} ;
305 mli
.cl_parameters
<- merge_parameters mli
.cl_parameters ml
.cl_parameters
;
307 (* we must reassociate comments in @param to the the corresponding
308 parameters because the associated comment of a parameter may have been changed y the merge.*)
309 Odoc_class.class_update_parameters_text mli
;
318 Class_attribute a2
->
319 if a2
.att_value
.val_name
= a
.att_value
.val_name
then
321 a
.att_value
.val_info
<- merge_info_opt merge_options
322 a
.att_value
.val_info a2
.att_value
.val_info
;
323 a
.att_value
.val_loc
<- { a
.att_value
.val_loc
with loc_impl
= a2
.att_value
.val_loc
.loc_impl
} ;
324 if !Odoc_args.keep_code
then
325 a
.att_value
.val_code
<- a2
.att_value
.val_code
;
333 (* we look for the last attribute with this name defined in the implementation *)
334 (List.rev
(Odoc_class.class_elements ml
))
341 (Odoc_class.class_attributes mli
);
350 if m2
.met_value
.val_name
= m
.met_value
.val_name
then
352 m
.met_value
.val_info
<- merge_info_opt
353 merge_options m
.met_value
.val_info m2
.met_value
.val_info
;
354 m
.met_value
.val_loc
<- { m
.met_value
.val_loc
with loc_impl
= m2
.met_value
.val_loc
.loc_impl
} ;
355 (* merge the parameter names *)
356 m
.met_value
.val_parameters
<- (merge_parameters
357 m
.met_value
.val_parameters
358 m2
.met_value
.val_parameters
) ;
359 (* we must reassociate comments in @param to the corresponding
360 parameters because the associated comment of a parameter may have been changed by the merge.*)
361 Odoc_value.update_value_parameters_text m
.met_value
;
363 if !Odoc_args.keep_code
then
364 m
.met_value
.val_code
<- m2
.met_value
.val_code
;
373 (* we look for the last method with this name defined in the implementation *)
374 (List.rev
(Odoc_class.class_elements ml
))
381 (Odoc_class.class_methods mli
)
383 (** merge of two t_class_type, one for a .mli, another for the .ml.
384 The .mli class is completed with the information in the .ml class. *)
385 let merge_class_types merge_options mli ml
=
386 mli
.clt_info
<- merge_info_opt merge_options mli
.clt_info ml
.clt_info
;
387 mli
.clt_loc
<- { mli
.clt_loc
with loc_impl
= ml
.clt_loc
.loc_impl
} ;
395 Class_attribute a2
->
396 if a2
.att_value
.val_name
= a
.att_value
.val_name
then
398 a
.att_value
.val_info
<- merge_info_opt merge_options
399 a
.att_value
.val_info a2
.att_value
.val_info
;
400 a
.att_value
.val_loc
<- { a
.att_value
.val_loc
with loc_impl
= a2
.att_value
.val_loc
.loc_impl
} ;
401 if !Odoc_args.keep_code
then
402 a
.att_value
.val_code
<- a2
.att_value
.val_code
;
411 (* we look for the last attribute with this name defined in the implementation *)
412 (List.rev
(Odoc_class.class_type_elements ml
))
419 (Odoc_class.class_type_attributes mli
);
428 if m2
.met_value
.val_name
= m
.met_value
.val_name
then
430 m
.met_value
.val_info
<- merge_info_opt
431 merge_options m
.met_value
.val_info m2
.met_value
.val_info
;
432 m
.met_value
.val_loc
<- { m
.met_value
.val_loc
with loc_impl
= m2
.met_value
.val_loc
.loc_impl
} ;
433 m
.met_value
.val_parameters
<- (merge_parameters
434 m
.met_value
.val_parameters
435 m2
.met_value
.val_parameters
) ;
436 (* we must reassociate comments in @param to the the corresponding
437 parameters because the associated comment of a parameter may have been changed y the merge.*)
438 Odoc_value.update_value_parameters_text m
.met_value
;
440 if !Odoc_args.keep_code
then
441 m
.met_value
.val_code
<- m2
.met_value
.val_code
;
450 (* we look for the last method with this name defined in the implementation *)
451 (List.rev
(Odoc_class.class_type_elements ml
))
458 (Odoc_class.class_type_methods mli
)
461 (** merge of two t_module_type, one for a .mli, another for the .ml.
462 The .mli module is completed with the information in the .ml module. *)
463 let rec merge_module_types merge_options mli ml
=
464 mli
.mt_info
<- merge_info_opt merge_options mli
.mt_info ml
.mt_info
;
465 mli
.mt_loc
<- { mli
.mt_loc
with loc_impl
= ml
.mt_loc
.loc_impl
} ;
466 (* merge exceptions *)
473 Element_exception ex2
->
474 if ex2
.ex_name
= ex
.ex_name
then
476 ex
.ex_info
<- merge_info_opt merge_options ex
.ex_info ex2
.ex_info
;
477 ex
.ex_loc
<- { ex
.ex_loc
with loc_impl
= ex2
.ex_loc
.loc_impl
} ;
478 ex
.ex_code
<- (match ex
.ex_code
with None
-> ex2
.ex_code
| _ -> ex
.ex_code
) ;
486 (* we look for the last exception with this name defined in the implementation *)
487 (List.rev
(Odoc_module.module_type_elements ml
))
494 (Odoc_module.module_type_exceptions mli
);
503 if ty2
.ty_name
= ty
.ty_name
then
505 merge_types merge_options ty ty2
;
513 (* we look for the last type with this name defined in the implementation *)
514 (List.rev
(Odoc_module.module_type_elements ml
))
521 (Odoc_module.module_type_types mli
);
522 (* merge submodules *)
530 if m2
.m_name
= m
.m_name
then
532 ignore
(merge_modules merge_options m m2
);
534 m.m_info <- merge_info_opt merge_options m.m_info m2.m_info;
535 m.m_loc <- { m.m_loc with loc_impl = m2.m_loc.loc_impl } ;
544 (* we look for the last module with this name defined in the implementation *)
545 (List.rev
(Odoc_module.module_type_elements ml
))
552 (Odoc_module.module_type_modules mli
);
554 (* merge module types *)
561 Element_module_type m2
->
562 if m2
.mt_name
= m
.mt_name
then
564 merge_module_types merge_options m m2
;
572 (* we look for the last module with this name defined in the implementation *)
573 (List.rev
(Odoc_module.module_type_elements ml
))
580 (Odoc_module.module_type_module_types mli
);
582 (* A VOIR : merge included modules ? *)
592 if v2
.val_name
= v
.val_name
then
594 v
.val_info
<- merge_info_opt merge_options v
.val_info v2
.val_info
;
595 v
.val_loc
<- { v
.val_loc
with loc_impl
= v2
.val_loc
.loc_impl
} ;
596 (* in the .mli we don't know any parameters so we add the ones in the .ml *)
597 v
.val_parameters
<- (merge_parameters
600 (* we must reassociate comments in @param to the the corresponding
601 parameters because the associated comment of a parameter may have been changed y the merge.*)
602 Odoc_value.update_value_parameters_text v
;
604 if !Odoc_args.keep_code
then
605 v
.val_code
<- v2
.val_code
;
614 (* we look for the last value with this name defined in the implementation *)
615 (List.rev
(Odoc_module.module_type_elements ml
))
622 (Odoc_module.module_type_values mli
);
632 if c2
.cl_name
= c
.cl_name
then
634 merge_classes merge_options c c2
;
642 (* we look for the last value with this name defined in the implementation *)
643 (List.rev
(Odoc_module.module_type_elements ml
))
650 (Odoc_module.module_type_classes mli
);
652 (* merge class types *)
659 Element_class_type c2
->
660 if c2
.clt_name
= c
.clt_name
then
662 merge_class_types merge_options c c2
;
670 (* we look for the last value with this name defined in the implementation *)
671 (List.rev
(Odoc_module.module_type_elements ml
))
678 (Odoc_module.module_type_class_types mli
)
680 (** merge of two t_module, one for a .mli, another for the .ml.
681 The .mli module is completed with the information in the .ml module. *)
682 and merge_modules merge_options mli ml
=
683 mli
.m_info
<- merge_info_opt merge_options mli
.m_info ml
.m_info
;
684 mli
.m_loc
<- { mli
.m_loc
with loc_impl
= ml
.m_loc
.loc_impl
} ;
685 let rec remove_doubles acc
= function
688 if List.mem h acc
then remove_doubles acc q
689 else remove_doubles (h
:: acc
) q
691 mli
.m_top_deps
<- remove_doubles mli
.m_top_deps ml
.m_top_deps
;
694 if !Odoc_args.keep_code
then
695 match mli
.m_code
, ml
.m_code
with
697 | _, Some s
-> Some s
703 if !Odoc_args.keep_code
then
704 match mli
.m_code_intf
, ml
.m_code_intf
with
706 | _, Some s
-> Some s
712 mli
.m_code_intf
<- code_intf;
714 (* merge exceptions *)
721 Element_exception ex2
->
722 if ex2
.ex_name
= ex
.ex_name
then
724 ex
.ex_info
<- merge_info_opt merge_options ex
.ex_info ex2
.ex_info
;
725 ex
.ex_loc
<- { ex
.ex_loc
with loc_impl
= ex
.ex_loc
.loc_impl
} ;
726 ex
.ex_code
<- (match ex
.ex_code
with None
-> ex2
.ex_code
| _ -> ex
.ex_code
) ;
734 (* we look for the last exception with this name defined in the implementation *)
735 (List.rev
(Odoc_module.module_elements ml
))
742 (Odoc_module.module_exceptions mli
);
751 if ty2
.ty_name
= ty
.ty_name
then
753 merge_types merge_options ty ty2
;
761 (* we look for the last type with this name defined in the implementation *)
762 (List.rev
(Odoc_module.module_elements ml
))
769 (Odoc_module.module_types mli
);
770 (* merge submodules *)
778 if m2
.m_name
= m
.m_name
then
780 ignore
(merge_modules merge_options m m2
);
782 m.m_info <- merge_info_opt merge_options m.m_info m2.m_info;
783 m.m_loc <- { m.m_loc with loc_impl = m2.m_loc.loc_impl } ;
792 (* we look for the last module with this name defined in the implementation *)
793 (List.rev
(Odoc_module.module_elements ml
))
800 (Odoc_module.module_modules mli
);
802 (* merge module types *)
809 Element_module_type m2
->
810 if m2
.mt_name
= m
.mt_name
then
812 merge_module_types merge_options m m2
;
820 (* we look for the last module with this name defined in the implementation *)
821 (List.rev
(Odoc_module.module_elements ml
))
828 (Odoc_module.module_module_types mli
);
830 (* A VOIR : merge included modules ? *)
838 if v2
.val_name
= v
.val_name
then
840 v
.val_info
<- merge_info_opt merge_options v
.val_info v2
.val_info
;
841 v
.val_loc
<- { v
.val_loc
with loc_impl
= v2
.val_loc
.loc_impl
} ;
842 (* in the .mli we don't know any parameters so we add the ones in the .ml *)
843 v
.val_parameters
<- (merge_parameters
846 (* we must reassociate comments in @param to the the corresponding
847 parameters because the associated comment of a parameter may have been changed y the merge.*)
848 Odoc_value.update_value_parameters_text v
;
850 if !Odoc_args.keep_code
then
851 v
.val_code
<- v2
.val_code
;
857 (* we look for the last value with this name defined in the implementation *)
858 (List.rev
(Odoc_module.module_values ml
))
865 (Odoc_module.module_values mli
);
875 if c2
.cl_name
= c
.cl_name
then
877 merge_classes merge_options c c2
;
885 (* we look for the last value with this name defined in the implementation *)
886 (List.rev
(Odoc_module.module_elements ml
))
893 (Odoc_module.module_classes mli
);
895 (* merge class types *)
902 Element_class_type c2
->
903 if c2
.clt_name
= c
.clt_name
then
905 merge_class_types merge_options c c2
;
913 (* we look for the last value with this name defined in the implementation *)
914 (List.rev
(Odoc_module.module_elements ml
))
921 (Odoc_module.module_class_types mli
);
925 let merge merge_options modules_list
=
926 let rec iter = function
929 (* look for another module with the same name *)
930 let (l_same
, l_others
) = List.partition
931 (fun m2
-> m
.m_name
= m2
.m_name
)
936 (* no other module to merge with *)
940 (* we can merge m with m2 if there is an implementation
942 let f b
= if !Odoc_args.inverse_merge_ml_mli
then not b
else b
in
943 match f m
.m_is_interface
, f m2
.m_is_interface
with
944 true, false -> (merge_modules merge_options m m2
) :: (iter l_others
)
945 | false, true -> (merge_modules merge_options m2 m
) :: (iter l_others
)
947 if !Odoc_args.inverse_merge_ml_mli
then
948 (* two Module.ts for the .mli ! *)
949 raise
(Failure
(Odoc_messages.two_interfaces m
.m_name
))
951 (* two Module.t for the .ml ! *)
952 raise
(Failure
(Odoc_messages.two_implementations m
.m_name
))
954 if !Odoc_args.inverse_merge_ml_mli
then
955 (* two Module.t for the .ml ! *)
956 raise
(Failure
(Odoc_messages.two_implementations m
.m_name
))
958 (* two Module.ts for the .mli ! *)
959 raise
(Failure
(Odoc_messages.two_interfaces m
.m_name
))
962 (* two many Module.t ! *)
963 raise
(Failure
(Odoc_messages.too_many_module_objects m
.m_name
))