summaryrefslogtreecommitdiffstats
path: root/ocamldoc/odoc_sig.ml
diff options
context:
space:
mode:
Diffstat (limited to 'ocamldoc/odoc_sig.ml')
-rw-r--r--ocamldoc/odoc_sig.ml258
1 files changed, 212 insertions, 46 deletions
diff --git a/ocamldoc/odoc_sig.ml b/ocamldoc/odoc_sig.ml
index 627938453..c2d365118 100644
--- a/ocamldoc/odoc_sig.ml
+++ b/ocamldoc/odoc_sig.ml
@@ -24,6 +24,7 @@ module Name = Odoc_name
open Odoc_parameter
open Odoc_value
open Odoc_type
+open Odoc_extension
open Odoc_exception
open Odoc_class
open Odoc_module
@@ -38,8 +39,7 @@ module Signature_search =
| T of string
| C of string
| CT of string
- | E of string
- | ER of string
+ | X of string
| P of string
type tab = (ele, Types.signature_item) Hashtbl.t
@@ -48,8 +48,8 @@ module Signature_search =
match signat with
Types.Sig_value (ident, _) ->
Hashtbl.add table (V (Name.from_ident ident)) signat
- | Types.Sig_exception (ident, _) ->
- Hashtbl.add table (E (Name.from_ident ident)) signat
+ | Types.Sig_typext (ident, _, _) ->
+ Hashtbl.add table (X (Name.from_ident ident)) signat
| Types.Sig_type (ident, _, _) ->
Hashtbl.add table (T (Name.from_ident ident)) signat
| Types.Sig_class (ident, _, _) ->
@@ -71,10 +71,9 @@ module Signature_search =
| (Types.Sig_value (_, val_desc)) -> val_desc.Types.val_type
| _ -> assert false
- let search_exception table name =
- match Hashtbl.find table (E name) with
- | (Types.Sig_exception (_, type_expr_list)) ->
- type_expr_list
+ let search_extension table name =
+ match Hashtbl.find table (X name) with
+ | (Types.Sig_typext (_, ext, _)) -> ext
| _ -> assert false
let search_type table name =
@@ -169,10 +168,44 @@ module Analyser =
let merge_infos = Odoc_merge.merge_info_opt Odoc_types.all_merge_options
- let name_comment_from_type_kind pos_end pos_limit tk =
- match tk with
- Parsetree.Ptype_abstract ->
- (0, [])
+ let name_comment_from_type_decl pos_end pos_limit ty_decl =
+ match ty_decl.Parsetree.ptype_kind with
+ | Parsetree.Ptype_abstract ->
+ let open Parsetree in
+ begin match ty_decl.ptype_manifest with
+ | None -> (0, [])
+ | Some core_ty ->
+ begin match core_ty.ptyp_desc with
+ | Ptyp_object (fields, _) ->
+ let rec f = function
+ | [] -> []
+ | ("",_,_) :: _ ->
+ (* Fields with no name have been eliminated previously. *)
+ assert false
+
+ | (name, _atts, ct) :: [] ->
+ let pos = ct.Parsetree.ptyp_loc.Location.loc_end.Lexing.pos_cnum in
+ let s = get_string_of_file pos pos_end in
+ let (_,comment_opt) = My_ir.just_after_special !file_name s in
+ [name, comment_opt]
+ | (name, _atts, ct) :: ((name2, _atts2, ct2) as ele2) :: q ->
+ let pos = ct.Parsetree.ptyp_loc.Location.loc_end.Lexing.pos_cnum in
+ let pos2 = ct2.Parsetree.ptyp_loc.Location.loc_start.Lexing.pos_cnum in
+ let s = get_string_of_file pos pos2 in
+ let (_,comment_opt) = My_ir.just_after_special !file_name s in
+ (name, comment_opt) :: (f (ele2 :: q))
+ in
+ let is_named_field field =
+ match field with
+ | ("",_,_) -> false
+ | _ -> true
+ in
+ (0, f @@ List.filter is_named_field fields)
+
+ | _ -> (0, [])
+ end
+ end
+
| Parsetree.Ptype_variant cons_core_type_list_list ->
let rec f acc cons_core_type_list_list =
let open Parsetree in
@@ -187,6 +220,7 @@ module Analyser =
let (len, comment_opt) = My_ir.just_after_special !file_name s in
(len, acc @ [ (pcd.pcd_name.txt, comment_opt) ])
| pcd :: (pcd2 :: _ as q) ->
+ (* TODO: support annotations on fields for inline records *)
let pos_end_first = pcd.pcd_loc.Location.loc_end.Lexing.pos_cnum in
let pos_start_second = pcd2.pcd_loc.Location.loc_start.Lexing.pos_cnum in
let s = get_string_of_file pos_end_first pos_start_second in
@@ -213,21 +247,58 @@ module Analyser =
(name.txt, comment_opt) :: (f (ele2 :: q))
in
(0, f name_mutable_type_list)
+ | Parsetree.Ptype_open ->
+ (0, [])
+
+
+ let manifest_structure env name_comment_list type_expr =
+ match type_expr.desc with
+ | Tobject (fields, _) ->
+ let f (field_name, _, type_expr) =
+ let comment_opt =
+ try List.assoc field_name name_comment_list
+ with Not_found -> None
+ in {
+ of_name = field_name ;
+ of_type = Odoc_env.subst_type env type_expr ;
+ of_text = comment_opt ;
+ }
+ in
+ Object_type (List.map f @@ fst @@ Ctype.flatten_fields fields)
+ | _ -> Other (Odoc_env.subst_type env type_expr)
+
+ let get_field env name_comment_list {Types.ld_id=field_name;ld_mutable=mutable_flag;ld_type=type_expr} =
+ let field_name = Ident.name field_name in
+ let comment_opt =
+ try List.assoc field_name name_comment_list
+ with Not_found -> None
+ in
+ {
+ rf_name = field_name ;
+ rf_mutable = mutable_flag = Mutable ;
+ rf_type = Odoc_env.subst_type env type_expr ;
+ rf_text = comment_opt
+ }
let get_type_kind env name_comment_list type_kind =
match type_kind with
Types.Type_abstract ->
Odoc_type.Type_abstract
| Types.Type_variant l ->
- let f {Types.cd_id=constructor_name;cd_args=type_expr_list;cd_res=ret_type} =
+ let f {Types.cd_id=constructor_name;cd_args;cd_res=ret_type} =
let constructor_name = Ident.name constructor_name in
let comment_opt =
- try List.assoc constructor_name name_comment_list
+ try List.assoc constructor_name name_comment_list
with Not_found -> None
in
+ let vc_args =
+ match cd_args with
+ | Cstr_tuple l -> Cstr_tuple (List.map (Odoc_env.subst_type env) l)
+ | Cstr_record l -> Cstr_record (List.map (get_field env []) l)
+ in
{
vc_name = constructor_name ;
- vc_args = List.map (Odoc_env.subst_type env) type_expr_list ;
+ vc_args;
vc_ret = may_map (Odoc_env.subst_type env) ret_type;
vc_text = comment_opt
}
@@ -235,20 +306,11 @@ module Analyser =
Odoc_type.Type_variant (List.map f l)
| Types.Type_record (l, _) ->
- let f {Types.ld_id=field_name;ld_mutable=mutable_flag;ld_type=type_expr} =
- let field_name = Ident.name field_name in
- let comment_opt =
- try List.assoc field_name name_comment_list
- with Not_found -> None
- in
- {
- rf_name = field_name ;
- rf_mutable = mutable_flag = Mutable ;
- rf_type = Odoc_env.subst_type env type_expr ;
- rf_text = comment_opt
- }
- in
- Odoc_type.Type_record (List.map f l)
+ Odoc_type.Type_record (List.map (get_field env name_comment_list) l)
+
+ | Types.Type_open ->
+ Odoc_type.Type_open
+
let erased_names_of_constraints constraints acc =
List.fold_right (fun constraint_ acc ->
@@ -267,6 +329,7 @@ module Analyser =
| Parsetree.Psig_attribute _
| Parsetree.Psig_extension _
| Parsetree.Psig_value _
+ | Parsetree.Psig_typext _
| Parsetree.Psig_exception _
| Parsetree.Psig_open _
| Parsetree.Psig_include _
@@ -297,7 +360,8 @@ module Analyser =
match ele2.Parsetree.pctf_desc with
Parsetree.Pctf_val (_, _, _, _)
| Parsetree.Pctf_method (_, _, _, _)
- | Parsetree.Pctf_constraint (_, _) -> loc.Location.loc_start.Lexing.pos_cnum
+ | Parsetree.Pctf_constraint (_, _)
+ | Parsetree.Pctf_attribute _ -> loc.Location.loc_start.Lexing.pos_cnum
| Parsetree.Pctf_inherit class_type ->
class_type.Parsetree.pcty_loc.Location.loc_start.Lexing.pos_cnum
| Parsetree.Pctf_extension _ -> assert false
@@ -456,6 +520,11 @@ module Analyser =
in
let (inher_l, eles) = f (pos_end + maybe_more) q in
(inh :: inher_l , eles_comments @ eles)
+ | Parsetree.Pctf_attribute _ ->
+ let (comment_opt, eles_comments) = get_comments_in_class last_pos loc.Location.loc_start.Lexing.pos_cnum in
+ let (inher_l, eles) = f loc.Location.loc_end.Lexing.pos_cnum q in
+ (inher_l, eles_comments @ eles)
+
| Parsetree.Pctf_extension _ -> assert false
in
f last_pos class_type_field_list
@@ -550,18 +619,105 @@ module Analyser =
let new_env = Odoc_env.add_value env v.val_name in
(maybe_more, new_env, [ Element_value v ])
- | Parsetree.Psig_exception exception_decl ->
- let name = exception_decl.Parsetree.pcd_name in
- let types_excep_decl =
- try Signature_search.search_exception table name.txt
+ | Parsetree.Psig_typext tyext ->
+ let new_env, types_ext_list, last_ext =
+ List.fold_left
+ (fun (env_acc, exts_acc, _) -> fun {Parsetree.pext_name = { txt = name }} ->
+ let complete_name = Name.concat current_module_name name in
+ let env_acc = Odoc_env.add_extension env_acc complete_name in
+ let types_ext =
+ try Signature_search.search_extension table name
+ with Not_found ->
+ raise (Failure (Odoc_messages.extension_not_found current_module_name name))
+ in
+ env_acc, ((name, types_ext) :: exts_acc), Some types_ext
+ )
+ (env, [], None)
+ tyext.Parsetree.ptyext_constructors
+ in
+ let ty_path, ty_params, priv =
+ match last_ext with
+ None -> assert false
+ | Some ext -> ext.ext_type_path, ext.ext_type_params, ext.ext_private
+ in
+ let new_te =
+ {
+ te_info = comment_opt;
+ te_type_name =
+ Odoc_env.full_type_name new_env (Name.from_path ty_path);
+ te_type_parameters =
+ List.map (Odoc_env.subst_type new_env) ty_params;
+ te_private = priv;
+ te_constructors = [];
+ te_loc = { loc_impl = None ; loc_inter = Some sig_item_loc} ;
+ te_code =
+ (
+ if !Odoc_global.keep_code then
+ Some (get_string_of_file pos_start_ele pos_end_ele)
+ else
+ None
+ ) ;
+ }
+ in
+ let rec analyse_extension_constructors maybe_more exts_acc types_ext_list =
+ match types_ext_list with
+ [] -> (maybe_more, List.rev exts_acc)
+ | (name, types_ext) :: q ->
+ let ext_loc_end = types_ext.Types.ext_loc.Location.loc_end.Lexing.pos_cnum in
+ let xt_args =
+ match types_ext.ext_args with
+ | Cstr_tuple l -> Cstr_tuple (List.map (Odoc_env.subst_type new_env) l)
+ | Cstr_record l -> Cstr_record (List.map (get_field new_env []) l)
+ in
+ let new_x =
+ {
+ xt_name = Name.concat current_module_name name ;
+ xt_args;
+ xt_ret = may_map (Odoc_env.subst_type new_env) types_ext.ext_ret_type ;
+ xt_type_extension = new_te;
+ xt_alias = None ;
+ xt_loc = { loc_impl = None ; loc_inter = Some types_ext.Types.ext_loc} ;
+ xt_text = None;
+ }
+ in
+ let pos_limit2 =
+ match q with
+ [] -> pos_limit
+ | (_, next) :: _ -> next.Types.ext_loc.Location.loc_start.Lexing.pos_cnum
+ in
+ let s = get_string_of_file ext_loc_end pos_limit2 in
+ let (maybe_more, comment_opt) = My_ir.just_after_special !file_name s in
+ new_x.xt_text <- comment_opt;
+ analyse_extension_constructors maybe_more (new_x :: exts_acc) q
+ in
+ let (maybe_more, exts) = analyse_extension_constructors 0 [] types_ext_list in
+ new_te.te_constructors <- exts;
+ let (maybe_more2, info_after_opt) =
+ My_ir.just_after_special
+ !file_name
+ (get_string_of_file (pos_end_ele + maybe_more) pos_limit)
+ in
+ new_te.te_info <- merge_infos new_te.te_info info_after_opt ;
+ (maybe_more + maybe_more2, new_env, [ Element_type_extension new_te ])
+
+ | Parsetree.Psig_exception ext ->
+ let name = ext.Parsetree.pext_name in
+ let types_ext =
+ try Signature_search.search_extension table name.txt
with Not_found ->
raise (Failure (Odoc_messages.exception_not_found current_module_name name.txt))
in
+ let ex_args =
+ match types_ext.ext_args with
+ | Cstr_tuple l -> Cstr_tuple (List.map (Odoc_env.subst_type env) l)
+ | Cstr_record l -> Cstr_record (List.map (get_field env []) l)
+ in
let e =
{
ex_name = Name.concat current_module_name name.txt ;
ex_info = comment_opt ;
- ex_args = List.map (Odoc_env.subst_type env) types_excep_decl.exn_args ;
+ ex_args;
+ ex_ret = may_map (Odoc_env.subst_type env) types_ext.ext_ret_type ;
ex_alias = None ;
ex_loc = { loc_impl = None ; loc_inter = Some sig_item_loc } ;
ex_code =
@@ -579,7 +735,7 @@ module Analyser =
(get_string_of_file pos_end_ele pos_limit)
in
e.ex_info <- merge_infos e.ex_info info_after_opt ;
- let new_env = Odoc_env.add_exception env e.ex_name in
+ let new_env = Odoc_env.add_extension env e.ex_name in
(maybe_more, new_env, [ Element_exception e ])
| Parsetree.Psig_type name_type_decl_list ->
@@ -613,10 +769,10 @@ module Analyser =
| td :: _ -> td.Parsetree.ptype_loc.Location.loc_start.Lexing.pos_cnum
in
let (maybe_more, name_comment_list) =
- name_comment_from_type_kind
+ name_comment_from_type_decl
type_decl.Parsetree.ptype_loc.Location.loc_end.Lexing.pos_cnum
pos_limit2
- type_decl.Parsetree.ptype_kind
+ type_decl
in
print_DEBUG ("Type "^name.txt^" : "^(match assoc_com with None -> "sans commentaire" | Some c -> Odoc_misc.string_of_info c));
let f_DEBUG (name, c_opt) = print_DEBUG ("constructor/field "^name^": "^(match c_opt with None -> "sans commentaire" | Some c -> Odoc_misc.string_of_info c)) in
@@ -645,9 +801,11 @@ module Analyser =
ty_kind = type_kind;
ty_private = sig_type_decl.Types.type_private;
ty_manifest =
- (match sig_type_decl.Types.type_manifest with
- None -> None
- | Some t -> Some (Odoc_env.subst_type new_env t));
+ begin match sig_type_decl.Types.type_manifest with
+ | None -> None
+ | Some t ->
+ Some (manifest_structure env name_comment_list t)
+ end ;
ty_loc = { loc_impl = None ; loc_inter = Some sig_item_loc } ;
ty_code =
(
@@ -866,7 +1024,7 @@ module Analyser =
in
(maybe_more, new_env2, [ Element_module_type mt ])
- | Parsetree.Psig_include (module_type, _attrs) ->
+ | Parsetree.Psig_include incl ->
let rec f = function
Parsetree.Pmty_ident longident ->
Name.from_longident longident.txt
@@ -885,7 +1043,7 @@ module Analyser =
end
| Parsetree.Pmty_extension _ -> assert false
in
- let name = f module_type.Parsetree.pmty_desc in
+ let name = f incl.Parsetree.pincl_mod.Parsetree.pmty_desc in
let full_name = Odoc_env.full_module_or_module_type_name env name in
let im =
{
@@ -1148,11 +1306,19 @@ module Analyser =
and analyse_module_kind
?(erased = Name.Set.empty) env current_module_name module_type sig_module_type =
match module_type.Parsetree.pmty_desc with
- Parsetree.Pmty_ident longident
- | Parsetree.Pmty_alias longident ->
+ | Parsetree.Pmty_ident longident ->
let k = analyse_module_type_kind env current_module_name module_type sig_module_type in
Module_with ( k, "" )
-
+ | Parsetree.Pmty_alias longident ->
+ begin
+ match sig_module_type with
+ Types.Mty_alias path ->
+ let alias_name = Odoc_env.full_module_name env (Name.from_path path) in
+ let ma = { ma_name = alias_name ; ma_module = None } in
+ Module_alias ma
+ | _ ->
+ raise (Failure "Parsetree.Pmty_alias _ but not Types.Mty_alias _")
+ end
| Parsetree.Pmty_signature signature ->
(
let signature = filter_out_erased_items_from_signature erased signature in