Reviewed By: jberdine Differential Revision: D20438569 fbshipit-source-id: 7db527273master
parent
04543938ab
commit
36b8ee7198
@ -1,84 +0,0 @@
|
|||||||
# Copyright (c) Facebook, Inc. and its affiliates.
|
|
||||||
#
|
|
||||||
# This source code is licensed under the MIT license found in the
|
|
||||||
# LICENSE file in the root directory of this source tree.
|
|
||||||
|
|
||||||
import logging
|
|
||||||
import os
|
|
||||||
|
|
||||||
from . import util
|
|
||||||
from inferlib import jwlib
|
|
||||||
|
|
||||||
MODULE_NAME = __name__
|
|
||||||
MODULE_DESCRIPTION = '''Run analysis of code built with a command like:
|
|
||||||
ant [options] [target]
|
|
||||||
|
|
||||||
Analysis examples:
|
|
||||||
infer -- ant compile'''
|
|
||||||
LANG = ['java']
|
|
||||||
|
|
||||||
|
|
||||||
def gen_instance(*args):
|
|
||||||
return AntCapture(*args)
|
|
||||||
|
|
||||||
|
|
||||||
# This creates an empty argparser for the module, which provides only
|
|
||||||
# description/usage information and no arguments.
|
|
||||||
create_argparser = util.base_argparser(MODULE_DESCRIPTION, MODULE_NAME)
|
|
||||||
|
|
||||||
|
|
||||||
class AntCapture:
|
|
||||||
|
|
||||||
def __init__(self, args, cmd):
|
|
||||||
self.args = args
|
|
||||||
util.log_java_version()
|
|
||||||
logging.info(util.run_cmd_ignore_fail([cmd[0], '-version']))
|
|
||||||
# TODO: make the extraction of targets smarter
|
|
||||||
self.build_cmd = [cmd[0], '-verbose'] + cmd[1:]
|
|
||||||
|
|
||||||
def is_interesting(self, content):
|
|
||||||
return self.is_quoted(content) or content.endswith('.java')
|
|
||||||
|
|
||||||
def is_quoted(self, argument):
|
|
||||||
quote = '\''
|
|
||||||
return len(argument) > 2 and argument[0] == quote\
|
|
||||||
and argument[-1] == quote
|
|
||||||
|
|
||||||
def remove_quotes(self, argument):
|
|
||||||
if self.is_quoted(argument):
|
|
||||||
return argument[1:-1]
|
|
||||||
else:
|
|
||||||
return argument
|
|
||||||
|
|
||||||
def get_infer_commands(self, verbose_output):
|
|
||||||
javac_pattern = '[javac]'
|
|
||||||
argument_start_pattern = 'Compilation arguments'
|
|
||||||
calls = []
|
|
||||||
javac_arguments = []
|
|
||||||
collect = False
|
|
||||||
for line in verbose_output.split('\n'):
|
|
||||||
if javac_pattern in line:
|
|
||||||
if argument_start_pattern in line:
|
|
||||||
collect = True
|
|
||||||
if javac_arguments != []:
|
|
||||||
capture = jwlib.create_infer_command(javac_arguments)
|
|
||||||
calls.append(capture)
|
|
||||||
javac_arguments = []
|
|
||||||
if collect:
|
|
||||||
pos = line.index(javac_pattern) + len(javac_pattern)
|
|
||||||
content = line[pos:].strip()
|
|
||||||
if self.is_interesting(content):
|
|
||||||
arg = self.remove_quotes(content)
|
|
||||||
javac_arguments.append(arg)
|
|
||||||
if javac_arguments != []:
|
|
||||||
capture = jwlib.create_infer_command(javac_arguments)
|
|
||||||
calls.append(capture)
|
|
||||||
javac_arguments = []
|
|
||||||
return calls
|
|
||||||
|
|
||||||
def capture(self):
|
|
||||||
(code, (verbose_out, _)) = util.get_build_output(self.build_cmd)
|
|
||||||
if code != os.EX_OK:
|
|
||||||
return code
|
|
||||||
cmds = self.get_infer_commands(verbose_out)
|
|
||||||
return util.run_compilation_commands(cmds)
|
|
@ -0,0 +1,73 @@
|
|||||||
|
(*
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*)
|
||||||
|
open! IStd
|
||||||
|
module L = Logging
|
||||||
|
|
||||||
|
let javac_pattern = "[javac]"
|
||||||
|
|
||||||
|
let arg_start_pattern = "Compilation arguments"
|
||||||
|
|
||||||
|
let extract_javac_args line =
|
||||||
|
let is_quoted s =
|
||||||
|
String.length s > 2 && String.is_prefix s ~prefix:"'" && String.is_suffix s ~suffix:"'"
|
||||||
|
in
|
||||||
|
let remove_quotes s = if is_quoted s then String.sub s ~pos:1 ~len:(String.length s - 2) else s in
|
||||||
|
let is_interesting s = String.is_suffix s ~suffix:".java" || is_quoted s in
|
||||||
|
Option.map (String.substr_index line ~pattern:javac_pattern) ~f:(fun pos ->
|
||||||
|
let content = String.drop_prefix line (pos + String.length javac_pattern) |> String.strip in
|
||||||
|
if is_interesting content then Some (remove_quotes content) else None )
|
||||||
|
|> Option.join
|
||||||
|
|
||||||
|
|
||||||
|
let do_javac_capture rev_javac_args =
|
||||||
|
let prog = Config.bin_dir ^/ "infer" in
|
||||||
|
let args =
|
||||||
|
"capture" :: "--continue" :: "--" :: "javac"
|
||||||
|
:: List.rev_filter_map rev_javac_args ~f:(fun arg ->
|
||||||
|
if String.equal "-Werror" arg then None
|
||||||
|
else if String.is_substring arg ~substring:"-g:" then Some "-g"
|
||||||
|
else Some arg )
|
||||||
|
in
|
||||||
|
L.debug Capture Verbose "%s %s@." prog (String.concat ~sep:" " args) ;
|
||||||
|
Process.create_process_and_wait ~prog ~args
|
||||||
|
|
||||||
|
|
||||||
|
type fold_state = {collecting: bool; rev_javac_args: string list}
|
||||||
|
|
||||||
|
let capture ~prog ~args =
|
||||||
|
let _, java_version =
|
||||||
|
Process.create_process_and_wait_with_output ~prog:"java" ~args:["-version"]
|
||||||
|
in
|
||||||
|
let _, javac_version =
|
||||||
|
Process.create_process_and_wait_with_output ~prog:"javac" ~args:["-version"]
|
||||||
|
in
|
||||||
|
let ant_version, _ = Process.create_process_and_wait_with_output ~prog ~args:["-version"] in
|
||||||
|
L.environment_info "%s %s %s@." java_version javac_version ant_version ;
|
||||||
|
L.debug Capture Verbose "%s %s@." prog @@ String.concat ~sep:" " args ;
|
||||||
|
let ant_out, _ = Process.create_process_and_wait_with_output ~prog ~args:("-verbose" :: args) in
|
||||||
|
L.debug Capture Verbose "%s" ant_out ;
|
||||||
|
let res =
|
||||||
|
List.fold (String.split_lines ant_out) ~init:{collecting= false; rev_javac_args= []}
|
||||||
|
~f:(fun {collecting; rev_javac_args} line ->
|
||||||
|
let is_line_interesting = String.is_substring line ~substring:javac_pattern in
|
||||||
|
if is_line_interesting then
|
||||||
|
let start_collecting = String.is_substring line ~substring:arg_start_pattern in
|
||||||
|
let collecting = collecting || start_collecting in
|
||||||
|
let rev_javac_args =
|
||||||
|
if start_collecting && not (List.is_empty rev_javac_args) then (
|
||||||
|
do_javac_capture rev_javac_args ; [] )
|
||||||
|
else rev_javac_args
|
||||||
|
in
|
||||||
|
let rev_javac_args =
|
||||||
|
if collecting then
|
||||||
|
Option.fold (extract_javac_args line) ~init:rev_javac_args ~f:(Fn.flip List.cons)
|
||||||
|
else rev_javac_args
|
||||||
|
in
|
||||||
|
{collecting; rev_javac_args}
|
||||||
|
else {collecting; rev_javac_args} )
|
||||||
|
in
|
||||||
|
if not (List.is_empty res.rev_javac_args) then do_javac_capture res.rev_javac_args
|
@ -0,0 +1,11 @@
|
|||||||
|
(*
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*)
|
||||||
|
|
||||||
|
open! IStd
|
||||||
|
|
||||||
|
val capture : prog:string -> args:string list -> unit
|
||||||
|
(** do an ant capture with the given prog (i.e. ant) and args *)
|
Loading…
Reference in new issue