[infer][java] support java -jar javac.jar

Summary:
Adds support for running the analysis using Java compilation commands of the form:
  java -jar compiler.jar ...

Reviewed By: sblackshear

Differential Revision: D3971517

fbshipit-source-id: 3659216
master
Jeremy Dubreil 8 years ago committed by Facebook Github Bot
parent dfa12b17f1
commit 650aa00dc9

@ -40,6 +40,7 @@ MODULE_TO_COMMAND = {
'buck': ['buck'], 'buck': ['buck'],
'gradle': ['gradle', 'gradlew'], 'gradle': ['gradle', 'gradlew'],
'javac': ['javac'], 'javac': ['javac'],
'java': ['java'],
'make': make.SUPPORTED_COMMANDS, 'make': make.SUPPORTED_COMMANDS,
'xcodebuild': ['xcodebuild'], 'xcodebuild': ['xcodebuild'],
'mvn': ['mvn'], 'mvn': ['mvn'],
@ -213,7 +214,9 @@ def main():
buck_not_in_compilation_database_mode = \ buck_not_in_compilation_database_mode = \
mod_name == 'buck' and not args.use_compilation_database mod_name == 'buck' and not args.use_compilation_database
if not (buck_not_in_compilation_database_mode or mod_name == 'javac'): if not (buck_not_in_compilation_database_mode or
mod_name == 'javac' or
mod_name == 'java'):
# Something should be already captured, otherwise analysis would fail # Something should be already captured, otherwise analysis would fail
if not os.path.exists(os.path.join(args.infer_out, 'captured')): if not os.path.exists(os.path.join(args.infer_out, 'captured')):
print('There was nothing to analyze, exiting') print('There was nothing to analyze, exiting')

@ -0,0 +1,62 @@
# Copyright (c) 2015 - present Facebook, Inc.
# All rights reserved.
#
# This source code is licensed under the BSD style license found in the
# LICENSE file in the root directory of this source tree. An additional grant
# of patent rights can be found in the PATENTS file in the same directory.
import argparse
import os
import subprocess
import traceback
import util
from inferlib import jwlib, utils
MODULE_NAME = __name__
MODULE_DESCRIPTION = '''Run analysis of code built with a command like:
java -jar compiler.jar <options> <source files>
Analysis examples:
infer -- java -jar compiler.jar srcfile.java
infer -- /path/to/java -jar compiler.jar srcfile.java'''
LANG = ['java']
def gen_instance(*args):
return JavaJarCapture(*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)
def parse_command_line(cmd):
cmd_parser = argparse.ArgumentParser()
cmd_parser.add_argument('-jar', type=utils.decode, metavar='Compiler jar')
java_jar, other_args = cmd_parser.parse_known_args(cmd[1:])
if java_jar.jar is None:
utils.stderr('Expects a javac command or jar file for the compiler')
utils.stderr('Example: infer -- java -jar compiler.jar ...\n')
exit(1)
return cmd[0], java_jar.jar, other_args
class JavaJarCapture:
def __init__(self, args, cmd):
java_binary, java_jar, other_args = parse_command_line(cmd)
self.analysis = jwlib.AnalyzerWithJavaJar(
args,
java_binary,
java_jar,
other_args
)
def capture(self):
try:
self.analysis.start()
return os.EX_OK
except subprocess.CalledProcessError as exc:
if self.analysis.args.debug:
traceback.print_exc()
return exc.returncode

@ -32,7 +32,7 @@ create_argparser = util.base_argparser(MODULE_DESCRIPTION, MODULE_NAME)
class JavacCapture: class JavacCapture:
def __init__(self, args, cmd): def __init__(self, args, cmd):
self.analysis = jwlib.AnalyzerWithFrontendWrapper( self.analysis = jwlib.AnalyzerWithJavac(
args, args,
cmd[0], cmd[0],
cmd[1:], cmd[1:],

@ -63,7 +63,7 @@ def create_infer_command(args, javac_arguments):
infer_args.append('--debug') infer_args.append('--debug')
infer_args += ['--analyzer', 'capture'] infer_args += ['--analyzer', 'capture']
return AnalyzerWithFrontendWrapper( return AnalyzerWithJavac(
analyze.infer_parser.parse_args(infer_args), analyze.infer_parser.parse_args(infer_args),
'javac', 'javac',
_get_javac_args(['javac'] + javac_arguments) _get_javac_args(['javac'] + javac_arguments)
@ -101,7 +101,7 @@ class CompilerCall(object):
def run(self): def run(self):
if self.args.version: if self.args.version:
return subprocess.call([self.javac_cmd] + self.original_arguments) return subprocess.call(self.javac_cmd + self.original_arguments)
else: else:
javac_args = ['-verbose', '-g'] javac_args = ['-verbose', '-g']
@ -113,8 +113,6 @@ class CompilerCall(object):
if self.args.classes_out is not None: if self.args.classes_out is not None:
javac_args += ['-d', self.args.classes_out] javac_args += ['-d', self.args.classes_out]
javac_args.append('-J-Duser.language=en')
classpath = self.args.classpath classpath = self.args.classpath
# the -processorpath option precludes searching the classpath for # the -processorpath option precludes searching the classpath for
# annotation processors, so we don't want to use it unless the # annotation processors, so we don't want to use it unless the
@ -215,7 +213,7 @@ class CompilerCall(object):
delete=False) as file_out: delete=False) as file_out:
self.verbose_out = file_out.name self.verbose_out = file_out.name
command = [self.javac_cmd] + cli_args + \ command = self.javac_cmd + cli_args + \
['@' + str(self.command_line_file)] ['@' + str(self.command_line_file)]
try: try:
subprocess.check_call(command, stderr=file_out) subprocess.check_call(command, stderr=file_out)
@ -239,14 +237,13 @@ class CompilerCall(object):
class AnalyzerWithFrontendWrapper(analyze.AnalyzerWrapper): class AnalyzerWithFrontendWrapper(analyze.AnalyzerWrapper):
def __init__(self, args, javac_cmd, javac_args): def __init__(self, infer_args, compiler_call):
self.javac = CompilerCall(javac_cmd, javac_args) analyze.AnalyzerWrapper.__init__(self, infer_args)
self.javac = compiler_call
if not self.javac.args.version: if not self.javac.args.version:
if javac_args is None: if self.javac.original_arguments is None:
raise Exception('No javac command detected') raise Exception('No javac command detected')
analyze.AnalyzerWrapper.__init__(self, args)
if self.args.buck: if self.args.buck:
self.args.infer_out = os.path.join( self.args.infer_out = os.path.join(
self.javac.args.classes_out, self.javac.args.classes_out,
@ -341,3 +338,19 @@ class AnalyzerWithFrontendWrapper(analyze.AnalyzerWrapper):
def _close(self): def _close(self):
os.remove(self.javac.verbose_out) os.remove(self.javac.verbose_out)
os.remove(self.javac.suppress_warnings_out) os.remove(self.javac.suppress_warnings_out)
class AnalyzerWithJavac(AnalyzerWithFrontendWrapper):
def __init__(self, infer_args, javac_executable, javac_args):
javac_cmd = [javac_executable, '-J-Duser.language=en']
compiler_call = CompilerCall(javac_cmd, javac_args)
AnalyzerWithFrontendWrapper.__init__(self, infer_args, compiler_call)
class AnalyzerWithJavaJar(AnalyzerWithFrontendWrapper):
def __init__(self, infer_args, java_executable, jar_path, compiler_args):
javac_cmd = [java_executable, '-jar', jar_path]
compiler_call = CompilerCall(javac_cmd, compiler_args)
AnalyzerWithFrontendWrapper.__init__(self, infer_args, compiler_call)

Loading…
Cancel
Save