@ -25,7 +25,6 @@ parser = argparse.ArgumentParser()
current_directory = utils . decode ( os . getcwd ( ) )
current_directory = utils . decode ( os . getcwd ( ) )
parser . add_argument ( ' -version ' , action = ' store_true ' )
parser . add_argument ( ' -d ' , dest = ' classes_out ' , default = current_directory )
parser . add_argument ( ' -d ' , dest = ' classes_out ' , default = current_directory )
@ -67,74 +66,65 @@ class CompilerCall(object):
self . args , self . remaining_args = parser . parse_known_args ( arguments )
self . args , self . remaining_args = parser . parse_known_args ( arguments )
self . verbose_out = None
self . verbose_out = None
def get_version ( self ) :
assert self . args . version
return subprocess . check_output (
self . javac_cmd + self . original_arguments ,
stderr = subprocess . STDOUT ) . strip ( )
def run ( self ) :
def run ( self ) :
if self . args . version :
javac_args = [ ' -verbose ' , ' -g ' ]
return subprocess . call ( self . javac_cmd + self . original_arguments )
else:
if self . args . classes_out is not None :
javac_args = [ ' -verbose ' , ' -g ' ]
javac_args + = [ ' -d ' , self . args . classes_out ]
if self . args . classes_out is not None :
javac_args + = self . remaining_args
javac_args + = [ ' -d ' , self . args . classes_out ]
def arg_must_go_on_cli ( arg ) :
javac_args + = self . remaining_args
# as mandated by javac, argument files must not contain
# arguments
def arg_must_go_on_cli ( arg ) :
return arg . startswith ( ' -J ' ) or arg . startswith ( ' @ ' )
# as mandated by javac, argument files must not contain
file_args = filter ( lambda x : not arg_must_go_on_cli ( x ) , javac_args )
# arguments
cli_args = filter ( arg_must_go_on_cli , javac_args )
return arg . startswith ( ' -J ' ) or arg . startswith ( ' @ ' )
file_args = filter ( lambda x : not arg_must_go_on_cli ( x ) , javac_args )
# pass non-special args via a file to avoid blowing up the
cli_args = filter ( arg_must_go_on_cli , javac_args )
# command line size limit
with tempfile . NamedTemporaryFile (
# pass non-special args via a file to avoid blowing up the
mode = ' w ' ,
# command line size limit
prefix = ' javac_args_ ' ,
with tempfile . NamedTemporaryFile (
delete = False ) as command_line :
mode = ' w ' ,
escaped_args = map ( lambda x : ' " %s " ' % ( x . replace ( ' " ' , ' \\ " ' ) ) ,
prefix = ' javac_args_ ' ,
file_args )
delete = False ) as command_line :
command_line . write ( utils . encode ( ' \n ' . join ( escaped_args ) ) )
escaped_args = map ( lambda x : ' " %s " ' % ( x . replace ( ' " ' , ' \\ " ' ) ) ,
command_line . write ( ' \n ' )
file_args )
self . command_line_file = command_line . name
command_line . write ( utils . encode ( ' \n ' . join ( escaped_args ) ) )
command_line . write ( ' \n ' )
with tempfile . NamedTemporaryFile (
self . command_line_file = command_line . name
mode = ' w ' ,
suffix = ' .out ' ,
with tempfile . NamedTemporaryFile (
prefix = ' javac_ ' ,
mode = ' w ' ,
delete = False ) as file_out :
suffix = ' .out ' ,
self . verbose_out = file_out . name
prefix = ' javac_ ' ,
delete = False ) as file_out :
command = self . javac_cmd + cli_args + \
self . verbose_out = file_out . name
[ ' @ ' + str ( self . command_line_file ) ]
try :
command = self . javac_cmd + cli_args + \
subprocess. check_call ( command , stderr = file_out )
[ ' @ ' + str ( self . command_line_file ) ]
except subprocess . CalledProcessError :
try :
try :
subprocess . check_call ( command , stderr = file_out )
fallback_command = [ ' javac ' ] + cli_args + \
[ ' @ ' + str ( self . command_line_file ) ]
subprocess . check_call (
fallback_command , stderr = file_out )
except subprocess . CalledProcessError :
except subprocess . CalledProcessError :
try :
error_msg = ' ERROR: failure during compilation ' \
fallback_command = [ ' javac ' ] + cli_args + \
+ ' command. \n You can run the failing ' \
[ ' @ ' + str ( self . command_line_file ) ]
+ ' compilation command again by ' \
subprocess . check_call (
+ ' copy-pasting the \n lines below in ' \
fallback_command , stderr = file_out )
+ ' your terminal: \n \n " " " \n ' \
except subprocess . CalledProcessError :
+ ' python <<EOF \n ' \
error_msg = ' ERROR: failure during compilation ' \
+ ' import subprocess \n ' \
+ ' command. \n You can run the failing ' \
+ ' cmd = {} \n ' \
+ ' compilation command again by ' \
+ ' subprocess.check_call(cmd) \n ' \
+ ' copy-pasting the \n lines below in ' \
+ ' EOF \n " " " \n '
+ ' your terminal: \n \n " " " \n ' \
failing_cmd = filter ( lambda arg : arg != ' -verbose ' ,
+ ' python <<EOF \n ' \
command )
+ ' import subprocess \n ' \
utils . stderr ( error_msg . format ( failing_cmd ) )
+ ' cmd = {} \n ' \
subprocess . check_call ( failing_cmd )
+ ' subprocess.check_call(cmd) \n ' \
+ ' EOF \n " " " \n '
failing_cmd = filter ( lambda arg : arg != ' -verbose ' ,
command )
utils . stderr ( error_msg . format ( failing_cmd ) )
subprocess . check_call ( failing_cmd )
return os . EX_OK
return os . EX_OK
@ -144,39 +134,27 @@ class AnalyzerWithFrontendWrapper(analyze.AnalyzerWrapper):
def __init__ ( self , infer_args , compiler_call ) :
def __init__ ( self , infer_args , compiler_call ) :
analyze . AnalyzerWrapper . __init__ ( self , infer_args )
analyze . AnalyzerWrapper . __init__ ( self , infer_args )
self . javac = compiler_call
self . javac = compiler_call
if not self . javac . args . version :
if self . javac . original_arguments is None :
if self . javac . original_arguments is None :
raise Exception ( ' No javac command detected ' )
raise Exception ( ' No javac command detected ' )
def compute_buck_key ( self ) :
javac_version = self . javac . get_version ( )
infer_version = utils . infer_key ( self . args . analyzer )
return ' / ' . join ( [ javac_version , infer_version ] )
def start ( self ) :
def start ( self ) :
if self . javac . args . version :
start_time = time . time ( )
if self . args . buck :
utils . stderr ( self . compute_buck_key ( ) )
self . _compile ( )
else :
if self . args . analyzer == config . ANALYZER_COMPILE :
return self . javac . run ( )
return os . EX_OK
else :
start_time = time . time ( )
self . _run_infer_frontend ( )
self . timing [ ' capture ' ] = utils . elapsed_time ( start_time )
self . _compile ( )
if self . args . analyzer == config . ANALYZER_CAPTURE :
if self . args . analyzer == config . ANALYZER_COMPILE :
return os . EX_OK
return os . EX_OK
self . analyze_and_report ( )
self . _run_infer_frontend ( )
self . _close ( )
self . timing [ ' capture ' ] = utils . elapsed_time ( start_time )
self . timing [ ' total ' ] = utils . elapsed_time ( start_time )
if self . args . analyzer == config . ANALYZER_CAPTURE :
self . save_stats ( )
return os . EX_OK
return self . stats
self . analyze_and_report ( )
self . _close ( )
self . timing [ ' total ' ] = utils . elapsed_time ( start_time )
self . save_stats ( )
return self . stats
def _run_infer_frontend ( self ) :
def _run_infer_frontend ( self ) :
infer_cmd = [ utils . get_cmd_in_bin_dir ( ' InferJava ' ) ]
infer_cmd = [ utils . get_cmd_in_bin_dir ( ' InferJava ' ) ]