123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212(* Yoann Padioleau
*
* Copyright (C) 2010 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.
*)openCommon(*****************************************************************************)(* Prelude *)(*****************************************************************************)(*
* Categorizing a source file according to recurring architecture "aspects"
* (really a directory structure) of a project. We often have some tests/,
* some commons/ library, some include/, etc.
*
* A file may belong to multiple categories at once.
*
* Right now the "aspects" are slightly modeled according to my
* own code and facebook flib code.
*
* This is used by codemap to colorize files. This is also used
* mainly for its AutoGenerated category in pfff -test_loc to
* not count auto generated code in the LOC of a project. This
* can also be used in the deadcode detector to not count auto
* generated files (e.g. visitor_xxx.ml) as real users of an entity.
*)(*****************************************************************************)(* Types *)(*****************************************************************************)(* coupling: if add category, dont forget to extend the source_archi_list
* below
*)typesource_archi=|Main|Init|Interface(* I put Test and Logging together because if some dirs do not have some
* unit tests, but have some code to logs his action, then it's quite
* similar. Such code should be more robust and it's good to see it
* visually.
*)|Test|Logging|Core|Utils(* utils base common *)|Constants|GetSet(* mutators, accessors *)|Configuration(* settings *)|Building(* makefiles *)|Data(* big files *)|Doc|Ui(* ui render display *)|Storage(* storage db *)|Parsing(* scanner, parser *)|Security|I18n(* todo?
* Memory (e.g. malloc, buffer), Fonts (font, charset)
* IO (e.g. keyboard, mouse)
* Strings (e.g. regex
*)|Architecture(* e.g. x86 *)|OS(* e.g. win32, macos, unix *)|Network(* e.g. protocols ssh, ftp *)|Ffi|ThirdParty(* external *)|Legacy(* legacy, deprecated *)|AutoGenerated|BoilerPlate(* a project often contains itself some infrastructure to run tests or
* benchmarks.
*)|Unittester|Profiler|MiniLite|Intern|Script|Regular(* with tarzan *)letsource_archi_list=[Main;Init;Interface;Test;Logging;Core;Utils;Configuration;Building;Doc;Data;Constants;GetSet;Ui;Storage;Parsing;Security;I18n;Architecture;OS;Network;Script;ThirdParty;Legacy;Ffi;AutoGenerated;BoilerPlate;Unittester;Profiler;MiniLite;Intern;Regular;]typesource_kind=|Header|Source(*****************************************************************************)(* String of *)(*****************************************************************************)(* ocamltarzan generated *)lets_of_source_archi=function|Init->"Init"|Main->"Main"|Interface->"Interface"|AutoGenerated->"AutoGenerated"|BoilerPlate->"BoilerPlate"|Test->"Test"|Logging->"Logging"|Core->"Core"|Utils->"Utils"|Constants->"Constants"|Script->"Script"|Ffi->"Ffi"|Configuration->"Configuration"|Building->"Building"|GetSet->"GetSet"|Ui->"Ui"|Storage->"Storage"|Parsing->"Parsing"|ThirdParty->"ThirdParty"|Legacy->"Legacy"|Unittester->"Unittester"|Profiler->"Profiler"|Intern->"Intern"|Regular->"Regular"|Doc->"Doc"|Data->"Data"|MiniLite->"MiniLite"|Security->"Security"|I18n->"I18n"|Architecture->"Architecture"|OS->"OS"|Network->"Network"(*****************************************************************************)(* Misc *)(*****************************************************************************)(* TODO move this elsewhere *)letfind_duplicate_dirnamedir=leth=Hashtbl.create101inletdups=Common2.hash_with_default(fun()->0)inletrecauxpath=letsubdirs=Common2.readdir_to_dir_listpath|>List.sortcompareinsubdirs|>List.iter(fundir->letpath=Filename.concatpathdirinifHashtbl.memhdirthenbeginpr2(spf"duplicate dir for %s already there: %s"dir(Hashtbl.findhdir));dups#updatedir(funold->old+1);endelsebeginHashtbl.addhdirpath;end;auxpath);inauxdir;pr2"duplicate are:";dups#to_list|>Common.sort_by_val_highfirst|>List.iter(fun(dir,cnt)->pr2(spf" %s: %d"dircnt););()(*****************************************************************************)(* actions *)(*****************************************************************************)(*
let actions () = [
"-test_dup_dir", "<dir>",
Common.mk_action_1_arg (find_duplicate_dirname);
]
*)