123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134(* 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.
*)openCommonmodulePI=Parse_infomoduleJ=Json_type(*****************************************************************************)(* Prelude *)(*****************************************************************************)(*****************************************************************************)(* Types *)(*****************************************************************************)(* could perhaps create a special file related to display of code ? *)typematch_format=(* ex: tests/misc/foo4.php:3
* foo(
* 1,
* 2);
*)|Normal(* ex: tests/misc/foo4.php:3: foo( *)|Emacs(* ex: tests/misc/foo4.php:3: foo(1,2) *)|OneLine(* ex: { check_id: ...; path: ...; start: ... end: ...; extra: ... *)|Json(*****************************************************************************)(* Globals *)(*****************************************************************************)(* used only for Json format *)letfirst_entry=reftrue(*****************************************************************************)(* Helpers *)(*****************************************************************************)(* When we print in the OneLine format we want to normalize the matched
* expression or code and so only print the tokens in the AST (and not
* the extra whitespace, newlines or comments). It's not enough though
* to just List.map str_of_info because some PHP expressions such as
* '$x = print FOO' would then be transformed into $x=printFOO, hence
* this function
*)letrecjoin_with_space_if_neededxs=matchxswith|[]->""|[x]->x|x::y::xs->ifx=~".*[a-zA-Z0-9_]$"&&y=~"^[a-zA-Z0-9_]"thenx^" "^(join_with_space_if_needed(y::xs))elsex^(join_with_space_if_needed(y::xs))letinfo_to_jsoncol_offsetinfo=letloc=PI.token_location_of_infoinfoinJ.Object["line",J.Intloc.PI.line;"col",J.Int(loc.PI.column+col_offset);](*****************************************************************************)(* Entry point *)(*****************************************************************************)letprint_match?(format=Normal)ii=let(mini,maxi)=PI.min_max_ii_by_posiiinlet(file,line)=PI.file_of_infomini,PI.line_of_infominiinletprefix=spf"%s:%d"filelineinletarr=Common2.cat_arrayfileinletlines=Common2.enum(PI.line_of_infomini)(PI.line_of_infomaxi)inmatchformatwith|Normal->prprefix;(* todo? some context too ? *)lines+>List.map(funi->arr.(i))+>List.iter(funs->pr(" "^s));|Emacs->pr(prefix^": "^arr.(List.hdlines))|OneLine->pr(prefix^": "^(ii+>List.mapPI.str_of_info+>join_with_space_if_needed))|Json->ifnot!first_entrythenpr",";first_entry:=false;letmatched_str=ii|>List.mapPI.str_of_info|>join_with_space_if_neededinletjson=J.Object[(* r2c: quite specific to r2c *)"check_id",J.String"pfff-parse_js_r2c";"path",J.Stringfile;"start",info_to_json0mini;"end",info_to_json(PI.str_of_infomaxi|>String.length)maxi;"extra",J.Object["matched_str",J.Stringmatched_str;(* todo: put metavars content *)];]inlets=Json_io.string_of_jsonjsoninprs(*****************************************************************************)(* Header/Trailer *)(*****************************************************************************)letprint_header=function|Normal|Emacs|OneLine->()|Json->pr"{ \"results\": [";first_entry:=trueletprint_trailer=function|Normal|Emacs|OneLine->()|Json->pr"] }";first_entry:=false