123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366#ifOCAML_VERSION>=(4,14,0)(* open Odoc_model.Lang.Source_info *)letpos_of_locloc=(loc.Location.loc_start.pos_cnum,loc.loc_end.pos_cnum)letcounter=letc=ref0infun()->incrc;!cmoduleEnv=structopenTypedtreeopenOdoc_model.Pathsletrecstructureenvparentstr=letenv'=Ident_env.add_structure_tree_itemsparentstrenvinList.iter(structure_itemenv'parent)str.str_itemsandsignatureenvparentsg=letenv'=Ident_env.add_signature_tree_itemsparentsgenvinList.iter(signature_itemenv'parent)sg.sig_itemsandsignature_itemenvparentitem=matchitem.sig_descwith|Tsig_modulemb->module_declarationenvparentmb|Tsig_recmodulembs->module_declarationsenvparentmbs|Tsig_modtypemtd->module_type_declarationenvparentmtd|Tsig_modtypesubstmtd->module_type_declarationenvparentmtd|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_idinmodule_typeenv(id:>Identifier.Signature.t)md.md_typeandmodule_declarationsenvparentmds=List.iter(module_declarationenvparent)mdsandmodule_type_declarationenv_parentmtd=letid=Ident_env.find_module_typeenvmtd.mtd_idinmatchmtd.mtd_typewith|None->()|Somemty->module_typeenv(id:>Identifier.Signature.t)mtyandstructure_itemenvparentitem=matchitem.str_descwith|Tstr_modulemb->module_bindingenvparentmb|Tstr_recmodulembs->module_bindingsenvparentmbs|Tstr_modtypemtd->module_type_declenvparentmtd|Tstr_open_|Tstr_value_|Tstr_class_|Tstr_eval_|Tstr_class_type_|Tstr_include_|Tstr_attribute_|Tstr_primitive_|Tstr_type_|Tstr_typext_|Tstr_exception_->()andmodule_type_declenv_parentmtd=letid=Ident_env.find_module_typeenvmtd.mtd_idinmatchmtd.mtd_typewith|None->()|Somemty->module_typeenv(id:>Identifier.Signature.t)mtyandmodule_typeenv(parent:Identifier.Signature.t)mty=matchmty.mty_descwith|Tmty_signaturesg->signatureenv(parent:Identifier.Signature.t)sg|Tmty_with(mty,_)->module_typeenvparentmty|Tmty_functor(_,t)->module_typeenvparentt|Tmty_ident_|Tmty_alias_|Tmty_typeof_->()andmodule_bindingsenvparentmbs=List.iter(module_bindingenvparent)mbsandmodule_bindingenv_parentmb=matchmb.mb_idwith|None->()|Someid->letid=Ident_env.find_module_identifierenvidinletid=(id:>Identifier.Module.t)inletinner=matchunwrap_module_expr_descmb.mb_expr.mod_descwith|Tmod_ident(_p,_)->()|_->letid=(id:>Identifier.Signature.t)inmodule_exprenvidmb.mb_exprininnerandmodule_exprenvparentmexpr=matchmexpr.mod_descwith|Tmod_ident_->()|Tmod_structurestr->structureenvparentstr|Tmod_functor(parameter,res)->letopenOdoc_model.Namesinletenv=matchparameterwith|Unit->env|Named(id_opt,_,arg)->(matchid_optwith|Someid->letenv=Ident_env.add_parameterparentid(ModuleName.of_identid)envinletid=Ident_env.find_module_identifierenvidinmodule_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_exprenvparentme|_->()andunwrap_module_expr_desc=function|Tmod_constraint(mexpr,_,Tmodtype_implicit,_)->unwrap_module_expr_descmexpr.mod_desc|desc->descletof_structure(id:Odoc_model.Paths.Identifier.RootModule.t)(s:Typedtree.structure)=letenv=Ident_env.empty()inlet()=structureenv(id:>Odoc_model.Paths.Identifier.Signature.t)sinenvendmoduleLocHashtbl=Hashtbl.Make(structtypet=Location.tletequall1l2=l1=l2lethash=Hashtbl.hashend)moduleIdentHashtbl=Hashtbl.Make(structtypet=Ident.tletequall1l2=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_idident_to_id=List.iter(function|Typedtree_traverse.Analysis.Definitionid,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)inIdentHashtbl.addident_to_idididentifier;LocHashtbl.addloc_to_idlocidentifier|_->())poses(* In order 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)=letcontinueanchorparent=anchor_of_identifier(anchor::acc)(parent:>Identifier.t)inletanchorkindname=Printf.sprintf"%s-%s"(Anchor.string_of_kindkind)nameinmatchid.ivwith|`InstanceVariable(parent,name)->letanchor=anchor`Val(InstanceVariableName.to_stringname)incontinueanchorparent|`Parameter(parent,name)asiv->letarg_num=Identifier.FunctorParameter.functor_arg_pos{idwithiv}inletkind=`Parameterarg_numinletanchor=anchorkind(ModuleName.to_stringname)incontinueanchorparent|`Module(parent,name)->letanchor=anchor`Module(ModuleName.to_stringname)incontinueanchorparent|`SourceDir_->assertfalse|`ModuleType(parent,name)->letanchor=anchor`ModuleType(ModuleTypeName.to_stringname)incontinueanchorparent|`Method(parent,name)->letanchor=anchor`Method(MethodName.to_stringname)incontinueanchorparent|`AssetFile_->assertfalse|`Field(parent,name)->letanchor=anchor`Field(FieldName.to_stringname)incontinueanchorparent|`SourceLocationMod_->assertfalse|`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_stringname)incontinueanchorparent|`Class(parent,name)->letanchor=anchor`Class(ClassName.to_stringname)incontinueanchorparent|`Page_->assertfalse|`LeafPage_->assertfalse|`CoreType_->assertfalse|`SourceLocation_->assertfalse|`ClassType(parent,name)->letanchor=anchor`ClassType(ClassTypeName.to_stringname)incontinueanchorparent|`SourcePage_->assertfalse|`Value(parent,name)->letanchor=anchor`Val(ValueName.to_stringname)incontinueanchorparent|`CoreException_->assertfalse|`Constructor(parent,name)->letanchor=anchor`Constructor(ConstructorName.to_stringname)incontinueanchorparent|`Root_->(* We do not need to include the "container" root module in the anchor
to have unique anchors. *)acc|`Extension(parent,name)->letanchor=anchor`Extension(ExtensionName.to_stringname)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_idid=letname=Odoc_model.Names.DefName.make_std(anchor_of_identifierid)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->((* In case 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_occurrencesposesuid_to_idident_to_id=List.filter_map(function|Typedtree_traverse.Analysis.Value(LocalValueuniq),loc->(matchIdentHashtbl.find_optident_to_iduniqwith|Someanchor->Some(Odoc_model.Lang.Source_info.Valueanchor,pos_of_locloc)|None->None)|Value(DefJmpx),loc->(matchUidHashtbl.find_optuid_to_idxwith|Someid->Some(Valueid,pos_of_locloc)|None->None)|Definition_,_->None)poses(* Add definition source info from the [loc_to_id] table *)letadd_definitionsloc_to_idoccurrences=LocHashtbl.fold(funlocidacc->(Odoc_model.Lang.Source_info.Definitionid,pos_of_locloc)::acc)loc_to_idoccurrencesletread_cmt_infossource_id_optidcmt_info=matchOdoc_model.Compat.shape_of_cmt_infoscmt_infowith|Someshape->(#ifOCAML_VERSION>=(5,2,0)letloc_of_declaration=letopenTypedtreeinfunction|Valuev->v.val_loc|Value_bindingvb->vb.vb_pat.pat_loc|Typet->t.typ_loc|Constructorc->c.cd_loc|Extension_constructore->e.ext_loc|Labell->l.ld_loc|Modulem->m.md_loc|Module_substitutionms->ms.ms_loc|Module_bindingmb->mb.mb_loc|Module_typemt->mt.mtd_loc|Classcd->cd.ci_id_name.loc|Class_typectd->ctd.ci_id_name.locinletuid_to_loc=Shape.Uid.Tbl.mapcmt_info.cmt_uid_to_declloc_of_declarationin#elseletuid_to_loc=cmt_info.cmt_uid_to_locin#endifmatch(source_id_opt,cmt_info.cmt_annots)with|Somesource_id,Implementationimpl->letenv=Env.of_structureidimplinlettraverse_infos=Typedtree_traverse.of_cmtenvuid_to_locimpl|>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.create10andident_to_id=IdentHashtbl.create10anduid_to_id=UidHashtbl.create10inlet()=(* populate [loc_to_id], [ident_to_id] and [uid_to_id] *)populate_local_defssource_idtraverse_infosloc_to_idident_to_id;populate_global_defsenvsource_idloc_to_iduid_to_locuid_to_idinletsource_infos=process_occurrencestraverse_infosuid_to_idident_to_id|>add_definitionsloc_to_idin(Some(shape,Shape.Uid.Tbl.to_mapuid_to_id),Some{Odoc_model.Lang.Source_info.id=source_id;infos=source_infos;})|_,_->(Some(shape,Odoc_model.Compat.empty_map),None))|None->(None,None)#elseletread_cmt_infos_source_id_opt_id_cmt_info=(None,None)#endif