123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405#ifOCAML_VERSION>=(4,14,0)letrecis_persistent:Path.t->bool=function|Path.Pidentid->Ident.persistentid|Path.Pdot(p,_)->is_persistentp|Path.Papply(p,_)->is_persistentp#ifOCAML_VERSION>=(5,1,0)|Path.Pextra_ty(p,_)->is_persistentp#endifletpos_of_locloc=(loc.Location.loc_start.pos_cnum,loc.loc_end.pos_cnum)letcounter=letc=ref0infun()->incr c;!cmoduleEnv=structopenTypedtreeopenOdoc_model.Pathsletrecstructure envparentstr=letenv'=Ident_env.add_structure_tree_itemsparentstrenvinList.iter(structure_itemenv'parent)str.str_itemsandsignatureenvparentsg=letenv'=Ident_env.add_signature_tree_itemsparentsgenvinList.iter(signature_item env'parent)sg.sig_itemsandsignature_itemenvparentitem=matchitem.sig_descwith|Tsig_module mb->module_declarationenvparentmb|Tsig_recmodulembs->module_declarations envparentmbs|Tsig_modtypemtd->module_type_declarationenvparentmtd|Tsig_modtypesubstmtd->module_type_declaration envparentmtd|Tsig_value_|Tsig_type_|Tsig_typesubst _|Tsig_typext_|Tsig_exception_|Tsig_modsubst_|Tsig_open_|Tsig_include_|Tsig_class_|Tsig_class_type_|Tsig_attribute_->()andmodule_declarationenv_parentmd=matchmd.md_idwith|None->()|Somemb_id ->letid=Ident_env.find_module_identifierenvmb_id inmodule_typeenv(id:>Identifier.Signature.t)md.md_typeandmodule_declarationsenvparent mds=List.iter(module_declaration envparent)mdsand module_type_declarationenv_parentmtd=letid=Ident_env.find_module_typeenvmtd.mtd_idinmatchmtd.mtd_typewith|None->()|Somemty->module_typeenv(id:>Identifier.Signature.t)mtyand structure_itemenvparentitem=matchitem.str_descwith|Tstr_module mb->module_bindingenvparentmb|Tstr_recmodulembs->module_bindings envparentmbs|Tstr_modtypemtd->module_type_declarationenvparentmtd|Tstr_open_|Tstr_value_|Tstr_class _|Tstr_eval_|Tstr_class_type_|Tstr_include_|Tstr_attribute_|Tstr_primitive_|Tstr_type_|Tstr_typext_|Tstr_exception_->()andmodule_typeenv(parent:Identifier.Signature.t)mty=match mty.mty_descwith|Tmty_signaturesg->signatureenv(parent:Identifier.Signature.t)sg|Tmty_with (mty,_)->module_type envparentmty|Tmty_functor(_,t)->module_typeenvparentt|Tmty_ident_|Tmty_alias_|Tmty_typeof _->()andmodule_bindingsenvparentmbs=List.iter(module_bindingenvparent)mbsandmodule_binding env_parent mb =matchmb.mb_idwith|None->()|Someid ->letid=Ident_env.find_module_identifierenvid inletid=(id:>Identifier.Module.t)inletinner=matchunwrap_module_expr_descmb.mb_expr.mod_descwith|Tmod_ident(_p,_)->()|_->letid=(id:>Identifier.Signature.t)inmodule_exprenvidmb.mb_exprininnerand module_exprenvparentmexpr=matchmexpr.mod_desc with|Tmod_ident _->()|Tmod_structurestr->structureenvparentstr|Tmod_functor(parameter,res)->letopenOdoc_model.Namesinletenv=matchparameter with|Unit->env|Named(id_opt,_,arg)->(matchid_optwith|Someid->letenv=Ident_env.add_parameterparentid(ModuleName.of_identid)envinlet id=Ident_env.find_module_identifierenvid inmodule_typeenv(id:>Identifier.Signature.t)arg;env|None ->env)inmodule_exprenv(Odoc_model.Paths.Identifier.Mk.resultparent)res|Tmod_constraint(me,_,constr,_)->let()=matchconstrwith|Tmodtype_implicit->()|Tmodtype_explicitmt->module_typeenvparentmtinmodule_exprenvparent me|_->()andunwrap_module_expr_desc=function|Tmod_constraint(mexpr,_,Tmodtype_implicit,_)->unwrap_module_expr_desc mexpr.mod_desc|desc->descletof_structure(id:Odoc_model.Paths.Identifier.RootModule.t)(s:Typedtree.structure)=let env=Ident_env.empty()inlet()=structureenv(id:>Odoc_model.Paths.Identifier.Signature.t)sinenvendmoduleLocHashtbl=Hashtbl.Make(structtypet=Location.tletequal l1l2=l1=l2lethash=Hashtbl.hashend)moduleIdentHashtbl=Hashtbl.Make(structtypet=Ident.tletequall1 l2=l1=l2lethash=Hashtbl.hashend)moduleAnnotHashtbl=Hashtbl.Make(structtypet=Odoc_model.Lang.Source_info.annotationOdoc_model.Lang.Source_info.with_posletequall1l2=l1=l2lethash=Hashtbl.hashend)moduleUidHashtbl =Shape.Uid.Tbl(* Adds the local definitions found in traverse infos to the [loc_to_id] and
[ident_to_id] tables. *)letpopulate_local_defssource_idposesloc_to_idlocal_ident_to_loc=List.iter(function|Typedtree_traverse.Analysis.LocalDefinitionid,loc->letname=Odoc_model.Names.LocalName.make_std(Printf.sprintf"local_%s_%d" (Ident.nameid)(counter()))inletidentifier=Odoc_model.Paths.Identifier.Mk.source_location_int(source_id,name)inLocHashtbl.addloc_to_idlocidentifier;IdentHashtbl.addlocal_ident_to_locidloc|_->())poses(* Inorder to turn an identifier into a source identifier, we need to generate
a unique anchor for any identifier. *)letanchor_of_identifierid=letopenOdoc_document.UrlinletopenOdoc_model.PathsinletopenOdoc_model.Namesinletrecanchor_of_identifieracc(id:Identifier.t)=letcontinue anchor parent=anchor_of_identifier(anchor::acc)(parent:>Identifier.t)inletanchorkindname=Printf.sprintf"%s-%s"(Anchor.string_of_kind kind)nameinmatchid.ivwith|`InstanceVariable(parent,name)->letanchor=anchor`Val(InstanceVariableName.to_string name)incontinueanchorparent|`Parameter(parent,name)asiv->letarg_num=Identifier.FunctorParameter.functor_arg_pos{idwithiv}inletkind=`Parameterarg_numinletanchor=anchorkind(ModuleName.to_stringname)incontinue anchorparent|`Module(parent,name)->letanchor=anchor`Module(ModuleName.to_stringname)incontinueanchorparent|`ModuleType(parent,name)->letanchor=anchor`ModuleType(ModuleTypeName.to_stringname)incontinueanchorparent|`Method(parent,name)->letanchor=anchor`Method(MethodName.to_stringname)incontinueanchorparent|`AssetFile_->assert false|`Field(parent,name)->letanchor=anchor`Field(FieldName.to_stringname)incontinueanchorparent|`SourceLocationMod_->assert false|`Resultparent->anchor_of_identifieracc(parent:>Identifier.t)|`SourceLocationInternal_->assertfalse|`Type(parent,name)->letanchor=anchor`Type(TypeName.to_stringname)incontinueanchorparent|`Label_->assertfalse|`Exception (parent,name)->letanchor=anchor`Exception(ExceptionName.to_string name)incontinueanchorparent|`Class(parent,name)->let anchor=anchor`Class(TypeName.to_stringname)incontinueanchorparent|`Page_->assertfalse|`LeafPage _->assertfalse|`SourceLocation_->assertfalse|`ClassType(parent,name)->letanchor=anchor`ClassType(TypeName.to_stringname)incontinueanchorparent|`SourcePage_->assert false|`Value(parent,name)->letanchor=anchor`Val(ValueName.to_stringname)incontinueanchorparent|`Constructor(parent,name)->letanchor=anchor`Constructor(ConstructorName.to_stringname)incontinueanchorparent|`Root_->(* We donot need to include the "container" root module in the anchor
to have unique anchors. *)acc|`Extension(parent,name)->letanchor=anchor`Extension(ExtensionName.to_string name)incontinueanchorparent|`ExtensionDecl(parent,name,_)->letanchor=anchor`ExtensionDecl(ExtensionName.to_stringname)incontinueanchorparentinanchor_of_identifier[]id|>String.concat"."(* Adds the global definitions, found in the [uid_to_loc], to the [loc_to_id]
and [uid_to_id] tables. *)letpopulate_global_defsenvsource_idloc_to_iduid_to_locuid_to_id=letmk_src_id id=letname=Odoc_model.Names.DefName.make_std(anchor_of_identifier id)in(Odoc_model.Paths.Identifier.Mk.source_location(source_id,name):>Odoc_model.Paths.Identifier.SourceLocation.t)inlet()=Ident_env.iter_located_identifierenv@@funlocid->LocHashtbl.addloc_to_idloc(mk_src_idid)inletmk_src_id()=letname =Odoc_model.Names.DefName.make_std(Printf.sprintf"def_%d"(counter()))in(Odoc_model.Paths.Identifier.Mk.source_location(source_id,name):>Odoc_model.Paths.Identifier.SourceLocation.t)inShape.Uid.Tbl.iter(funuidloc->ifloc.Location.loc_ghostthen()elsematchLocHashtbl.find_optloc_to_idlocwith|Someid->UidHashtbl.adduid_to_iduidid|None->((* Incase there is no entry for the location of the uid, we add one. *)matchuidwith|Item_->letid=mk_src_id()inLocHashtbl.addloc_to_idlocid;UidHashtbl.adduid_to_iduidid|Compilation_unit_->()|_->()))uid_to_loc(* Extract [Typedtree_traverse] occurrence information and turn them into proper
source infos *)letprocess_occurrencesenvposesloc_to_idlocal_ident_to_loc=let openOdoc_model.Lang.Source_infoin(* Ensure source infos are not repeated by putting them in a Set (a unit hashtbl) *)letocc_tbl=AnnotHashtbl.create100inletprocesspfind_in_env=matchpwith|Path.PidentidwhenIdentHashtbl.memlocal_ident_to_locid->(matchLocHashtbl.find_optloc_to_id(IdentHashtbl.findlocal_ident_to_locid)with|None->None|Someid->letdocumentation=Noneandimplementation=Some(Resolved id)inSome{documentation;implementation})|p->(matchfind_in_envenvpwith|path->letdocumentation=ifis_persistentpthenSomepathelseNoneandimplementation=Some(Unresolvedpath)inSome{documentation;implementation }|exception_->None)inList.iter(function|Typedtree_traverse.Analysis.Valuep,loc->processpIdent_env.Path.read_value|>Option.iter@@funl->AnnotHashtbl.replaceocc_tbl(Valuel,pos_of_locloc)()|Module p,loc->process pIdent_env.Path.read_module|>Option.iter@@funl->AnnotHashtbl.replaceocc_tbl(Modulel,pos_of_locloc)()|ModuleType p,loc->processpIdent_env.Path.read_module_type|>Option.iter@@funl->AnnotHashtbl.replaceocc_tbl(ModuleTypel,pos_of_locloc)()|Typep,loc->processpIdent_env.Path.read_type|>Option.iter@@funl->AnnotHashtbl.replaceocc_tbl(Typel,pos_of_locloc)()|LocalDefinition _,_->())poses;AnnotHashtbl.fold(funk()acc->k::acc)occ_tbl[](* Add definition source info from the [loc_to_id] table *)letadd_definitionsloc_to_idoccurrences=LocHashtbl.fold(funlocidacc->(Odoc_model.Lang.Source_info.Definition id,pos_of_locloc)::acc)loc_to_idoccurrencesletread_cmt_infossource_idshape_infoimpldigestrootimports =matchshape_infowith|Some (shape,uid_to_loc)->letfake_root_id=Odoc_model.Paths.Identifier.Mk.root(None,Odoc_model.Names.ModuleName.make_std"fake_root")inletenv=Env.of_structurefake_root_idimplinlettraverse_infos=Typedtree_traverse.of_cmtenvimpl|>List.rev(* Information are accumulated in a list. We need to have the
first info first in the list, to assign anchors with increasing
numbers, so that adding some content at the end of a file does
not modify the anchors for existing anchors. *)inletloc_to_id=LocHashtbl.create10andlocal_ident_to_loc=IdentHashtbl.create10anduid_to_id =UidHashtbl.create10inlet()=matchsource_idwith|None->()|Somesource_id->populate_local_defssource_idtraverse_infosloc_to_idlocal_ident_to_loc;populate_global_defsenvsource_idloc_to_iduid_to_locuid_to_idinletsource_infos=process_occurrencesenvtraverse_infosloc_to_idlocal_ident_to_loc|>add_definitionsloc_to_idinletshape_info=Some(shape,Shape.Uid.Tbl.to_mapuid_to_id)in{Odoc_model.Lang.Implementation.id=source_id;source_info=source_infos;digest;root;linked=false;shape_info;imports;}|Noneasshape_info ->{Odoc_model.Lang.Implementation.id=source_id;source_info=[];digest;root;linked=false;shape_info;imports;}#elseletread_cmt_infossource_idshape_info_impldigestrootimports={Odoc_model.Lang.Implementation.id=source_id;source_info=[];digest;root;linked=false;shape_info;imports;}#endif