[clang] Parse compilation database coming from xcpretty

Reviewed By: jvillard

Differential Revision: D4058793

fbshipit-source-id: 4b6a06d
master
Dulma Churchill 8 years ago committed by Facebook Github Bot
parent 8ea40b29b0
commit 4f6aa5e408

@ -13,10 +13,12 @@ open! Utils;
/** quoting style of the arguments */
type style =
| EscapedDoubleQuotes /** the arguments should be enclosed in "double quotes" and are already escaped */
| SingleQuotes /** the arguments should be enclosed in 'single quotes' and have to be escaped */;
| SingleQuotes /** the arguments should be enclosed in 'single quotes' and have to be escaped */
| EscapedNoQuotes /** the arguments should not be enclosed in quotes and are already escaped */;
let quote style =>
switch style {
| EscapedNoQuotes => (fun s => s)
| EscapedDoubleQuotes => (fun s => "\"" ^ s ^ "\"")
| SingleQuotes =>
let map = (

@ -8,10 +8,11 @@
*/
/* module for escaping clang arguments on the command line and put them into files */
/** quoting style */
/** quoting style of the arguments */
type style =
| EscapedDoubleQuotes /** the arguments should be enclosed in "double quotes" and are already escaped */
| SingleQuotes /** the arguments should be enclosed in 'single quotes' and have to be escaped */;
| SingleQuotes /** the arguments should be enclosed in 'single quotes' and have to be escaped */
| EscapedNoQuotes /** the arguments should not be enclosed in quotes and are already escaped */;
let quote: style => string => string;

@ -12,7 +12,7 @@ open! Utils
type compilation_data = {
dir : string;
command : string;
args : string list;
args : string;
}
type t = compilation_data StringMap.t ref
@ -24,31 +24,51 @@ let iter database f = StringMap.iter f !database
let find database key = StringMap.find key !database
let parse_command_and_arguments command_and_arguments =
let regexp = Str.regexp "[^\\][ ]" in
let index = Str.search_forward regexp command_and_arguments 0 in
let command = Str.string_before command_and_arguments (index+1) in
let arguments = Str.string_after command_and_arguments (index+1) in
command, arguments
(** Parse the compilation database json file into the compilationDatabase
map. The json file consists of an array of json objects that contain the file
to be compiled, the directory to be compiled in, and the compilation command as a list
and as a string. We pack this information into the compilationDatabase map, and remove the
clang invocation part, because we will use a clang wrapper. *)
let decode_json_file (database : t) should_add_file json_path =
let exit_format_error () =
failwith ("Json file doesn't have the expected format") in
let json = Yojson.Basic.from_file json_path in
let parse_argument compilation_argument =
match compilation_argument with
| `String arg -> arg
| _ -> failwith ("Json file doesn't have the expected format") in
let get_dir el =
match el with
| ("directory", `String dir) -> Some dir
| _ -> None in
let get_file el =
match el with
| ("file", `String file) -> Some file
| _ -> None in
let get_cmd el =
match el with
| ("command", `String cmd) -> Some cmd
| _ -> None in
let rec parse_json json =
match json with
| `List arguments ->
IList.iter parse_json arguments
| `Assoc [ ("directory", `String dir);
("file", `String file_path);
("arguments", `List compilation_arguments);
("command", `String _) ] ->
(match IList.map parse_argument compilation_arguments with
| [] -> failwith ("Command cannot be empty")
| command :: args when should_add_file file_path ->
let compilation_data = { dir; command; args;} in
database := StringMap.add file_path compilation_data !database
| _ -> ())
| _ ->
failwith ("Json file doesn't have the expected format") in
| `Assoc l ->
let dir = match IList.find_map_opt get_dir l with
| Some dir -> dir
| None -> exit_format_error () in
let file = match IList.find_map_opt get_file l with
| Some file -> file
| None -> exit_format_error () in
let cmd = match IList.find_map_opt get_cmd l with
| Some cmd -> cmd
| None -> exit_format_error () in
let command, args = parse_command_and_arguments cmd in
if should_add_file file then
let compilation_data = { dir; command; args;} in
database := StringMap.add file compilation_data !database
| _ -> exit_format_error () in
parse_json json

@ -14,7 +14,7 @@ type t
type compilation_data = {
dir : string;
command : string;
args : string list;
args : string;
}
val empty : unit -> t

@ -81,27 +81,13 @@ let swap_command cmd =
(* The command in the compilation database json emitted by buck can only be clang or clang++ *)
failwithf "Unexpected command name in Buck compilation database: %s" cmd
(** We have to replace the .o files because the path in buck-out doesn't exist at this point.
Moreover, in debug mode we create debug files in the place where the .o files are created,
so having all that in the results directory is convenient for finding the files and for
scanning the directory for running clang_frontend_stats. *)
let replace_clang_arg arg =
if Filename.check_suffix arg ".o" then
let dir = Config.results_dir // Config.clang_build_output_dir_name in
let abbrev_source_file = DB.source_file_encoding (DB.source_file_from_string arg) in
[dir // abbrev_source_file]
(* Doing this argument manipulation here rather than in the wrappers because it seems to
be needed only with this integration.*)
else if (arg = "-include-pch") || (Filename.check_suffix arg ".gch") then []
else [arg]
let run_compilation_file compilation_database file =
try
let compilation_data = CompilationDatabase.find compilation_database file in
let wrapper_cmd = swap_command compilation_data.command in
let replaced_args = IList.map replace_clang_arg compilation_data.args |> IList.flatten in
let arg_file =
ClangQuotes.mk_arg_file "buck_clang_args_" ClangQuotes.SingleQuotes replaced_args in
ClangQuotes.mk_arg_file
"cdb_clang_args_" ClangQuotes.EscapedNoQuotes [compilation_data.args] in
let args = Array.of_list [wrapper_cmd; "@" ^ arg_file] in
let env = Array.append
(Unix.environment())

Loading…
Cancel
Save