123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186(* Yoann Padioleau
*
* Copyright (C) 2010-2011 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.
*)openCommonmoduleDb=Database_codemoduleHC=Highlight_codemodulePI=Parse_info(*****************************************************************************)(* Prelude *)(*****************************************************************************)(*
* We abuse the code highlighter to also compute the light database.
*)(*****************************************************************************)(* Helpers *)(*****************************************************************************)(* pre: the info corresponds to a originTok, otherwise
* file_of_info could give the location of the macro file
* and filename_without_leading_path will not like it
*)letmk_entity~root~hcomplete_name_of_infoinfocateg=lets=PI.str_of_infoinfoin(*pr2 (spf "mk_entity %s" s);*)letl=PI.line_of_infoinfoinletc=PI.col_of_infoinfoinletname=sinletfullname=tryHashtbl.findhcomplete_name_of_infoinfo|>sndwithNot_found->""in{Database_code.e_name=name;e_fullname=iffullname<>namethenfullnameelse"";e_file=PI.file_of_infoinfo|>Common.readable~root;e_pos={Common2.l=l;c};e_kind=Common2.some(Database_code.entity_kind_of_highlight_category_defcateg);(* filled in step 2 *)e_number_external_users=0;(* TODO *)e_good_examples_of_use=[];(* TODO *)e_properties=[];}(*****************************************************************************)(* Main entry point *)(*****************************************************************************)letcompute_database?(verbose=false)files_or_dirs=(* when we want to merge this database with the db of another language
* like PHP, the other database may use realpath for the path of the files
* so we want to behave the same.
*)letfiles_or_dirs=files_or_dirs|>List.mapCommon.fullpathinletroot=Common2.common_prefix_of_files_or_dirsfiles_or_dirsinpr2(spf"generating C/C++ db_light with root = %s"root);letfiles=Lib_parsing_cpp.find_source_files_of_dir_or_filesfiles_or_dirsinletdirs=files|>List.mapFilename.dirname|>Common2.uniq_effin(* step1: collecting definitions *)ifverbosethenpr2"phase 1: collecting definitions";let(hdefs:(string,Db.entity)Hashtbl.t)=Hashtbl.create1001inlet(hdefs_pos:(Parse_info.t,bool)Hashtbl.t)=Hashtbl.create1001infiles|>Console.progress~show:verbose(funk->List.iter(funfile->k();let(ast2,_stat)=Parse_cpp.parsefileinlethcomplete_name_of_info=(*Class_js.extract_complete_name_of_info ast *)Hashtbl.create101inast2|>List.iter(fun(ast,toks)->letprefs=Highlight_code.default_highlighter_preferencesinHighlight_cpp.visit_toplevel~tag_hook:(funinfocateg->(* todo? could look at the info of the origintok of the expanded? *)ifnot(PI.is_origintokinfo)then()else(* todo: use is_entity_def_category ? *)matchcategwith|HC.Entity(_,(HC.Def2_))->Hashtbl.addhdefs_posinfotrue;lete=mk_entity~root~hcomplete_name_of_infoinfocateginHashtbl.addhdefse.Db.e_namee;|_->())prefs(ast,toks););));(* step2: collecting uses *)ifverbosethenpr2"\nphase 2: collecting uses";files|>Console.progress~show:verbose(funk->List.iter(funfile->k();let(ast2,_stat)=Parse_cpp.parsefileinletast=Parse_cpp.program_of_program2ast2in(* work by side effect on ast2 too *)Check_variables_cpp.check_and_annotate_programast;ast2|>List.iter(fun(ast,toks)->letprefs=Highlight_code.default_highlighter_preferencesinHighlight_cpp.visit_toplevel~tag_hook:(funinfocateg->ifnot(PI.is_origintokinfo)then()elsematchcategwith|HC.Entity(_,(HC.Use2_))|HC.StructName(HC.Use)(*| HC.Method (HC.Use2 _) *)->lets=PI.str_of_infoinfoinHashtbl.find_allhdefss|>List.iter(funentity->letfile_entity=entity.Db.e_filein(* todo: check corresponding entity_kind ? *)iffile_entity<>file&&Db.entity_and_highlight_category_correpondanceentitycategthenbeginentity.Db.e_number_external_users<-entity.Db.e_number_external_users+1;end);|_->())prefs(ast,toks););()));(* step3: adding cross reference information *)ifverbosethenpr2"\nphase 3: last fixes";letentities_arr=Common.hash_to_listhdefs|>List.mapsnd|>Array.of_listinDb.adjust_method_or_field_external_users~verboseentities_arr;letdirs=dirs|>List.map(funs->Common.readable~roots)inletdirs=Db.alldirs_and_parent_dirs_of_relative_dirsdirsin{Db.root=root;dirs=dirs|>List.map(fund->d,0);(* TODO *)files=files|>List.map(funf->Common.readable~rootf,0);(* TODO *)entities=entities_arr;}