123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121(* Yoann Padioleau
*
* Copyright (C) 2013 Facebook
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation, with the
* special exception on linking described in file license.txt.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the file
* license.txt for more details.
*)openCommonmoduleG=Graph_codemoduleE=Entity_codemoduleD=Database_code(*****************************************************************************)(* Prelude *)(*****************************************************************************)(*
* Generating a (light) database from a graph_code.
*)(*****************************************************************************)(* Helpers *)(*****************************************************************************)(*****************************************************************************)(* Main entry point *)(*****************************************************************************)letdb_of_graph_coderootg=(* todo: if at some point we want to also leverage the
* cross entity functionality of Database_code, e.g.
* its e_good_examples_of_use field, then we need to
* do something a bit different here and map
* nodes to indices first.
*)let(res:D.entitylistref)=ref[]inlethfiles=Hashtbl.create101inlethdirs=Hashtbl.create101in(* opti: using G.parent and check if G.not_found is slow *)lethnot_found=G.node_and_all_childrenG.not_foundg|>Common.hashset_of_listin(* opti: using G.pred is super slow *)letuse_pred=G.mk_eff_use_predging|>G.iter_nodes(funnode->let(s,kind)=nodeinmatchkindwith|E.Function|E.Class|E.Constant|E.Global|E.Type|E.Exception|E.Constructor|E.Field|E.Method|E.ClassConstant|E.Macro|E.Prototype|E.GlobalExtern->ifHashtbl.memhnot_foundnodethen()elsebeginletnodeinfo=tryG.nodeinfonodegwithNot_found->failwith(spf"No nodeinfo for %s"(G.string_of_nodenode))inletpos=nodeinfo.G.posinletfile=pos.Parse_info.filein(* they should be in readable path format *)Hashtbl.replacehfilesfiletrue;Hashtbl.replacehdirs(Filename.dirnamefile)true;(* select users that are outside! that are not in the same file *)letpred=use_prednodeinletextern=pred|>List.filter(funn->tryletfile2=G.file_of_nodenginfile<>file2withNot_found->false)inletnb_users=List.lengthexterninlete={Database_code.e_kind=kind;e_name=G.shortname_of_nodenode;e_fullname=s;e_file=pos.Parse_info.file;e_pos={Common2.l=pos.Parse_info.line;c=pos.Parse_info.column;};e_number_external_users=nb_users;(* todo *)e_good_examples_of_use=[];e_properties=[];}inCommon.pusheresend|E.TopStmts|E.Module|E.Package|E.Other_|E.File|E.Dir|E.MultiDirs->());letarr=Array.of_list!resin(* MultiDirs entities? they are done by codemap on the fly *){Database_code.root=root;files=Common2.hkeyshfiles|>List.map(funfile->file,0);dirs=Common2.hkeyshdirs|>List.map(fundir->dir,1);entities=arr;}