From 3dfaa9ed7b750eddf1dad6870aea94569cbf1f43 Mon Sep 17 00:00:00 2001 From: Josh Berdine Date: Fri, 16 Dec 2016 04:01:13 -0800 Subject: [PATCH] Remove support for SuppressWarnings annotations Summary: SuppressWarnings annotations are hardly used and add considerable complexity due to requiring recompilation with an annotation processor. Reviewed By: jvillard Differential Revision: D4312193 fbshipit-source-id: c4fc07e --- .gitignore | 1 - .../main/java/infer/other/MainActivity.java | 3 +- infer/annotations/Makefile | 10 +- .../annotprocess/CollectSuppressWarnings.java | 123 ------------------ .../javax.annotation.processing.Processor | 1 - infer/lib/python/inferlib/config.py | 5 - infer/lib/python/inferlib/jwlib.py | 100 -------------- infer/src/backend/inferconfig.ml | 27 ---- infer/src/backend/inferconfig.mli | 1 - infer/src/backend/reporting.ml | 6 +- infer/src/base/Config.ml | 8 -- infer/src/base/Config.mli | 2 - infer/src/checkers/annotations.ml | 5 +- infer/src/checkers/annotations.mli | 3 +- infer/src/java/jAnnotation.ml | 17 +-- infer/src/java/jAnnotation.mli | 2 +- infer/src/java/jTrans.ml | 18 +-- infer/tests/build_systems/ant/issues.exp | 1 - infer/tests/build_systems/buck/issues.exp | 1 - .../checkers/ExpensiveInheritanceExample.java | 4 +- .../codetoanalyze/java/checkers/issues.exp | 1 - .../eradicate/SuppressWarningsExample.java | 51 -------- .../codetoanalyze/java/eradicate/issues.exp | 2 - .../java/infer/NullPointerExceptions.java | 3 +- .../tests/codetoanalyze/java/infer/issues.exp | 1 - 25 files changed, 26 insertions(+), 370 deletions(-) delete mode 100644 infer/annotations/com/facebook/infer/annotprocess/CollectSuppressWarnings.java delete mode 100644 infer/annotations/resources/META-INF/services/javax.annotation.processing.Processor delete mode 100644 infer/tests/codetoanalyze/java/eradicate/SuppressWarningsExample.java diff --git a/.gitignore b/.gitignore index 2ee2db21c..058f3eefb 100644 --- a/.gitignore +++ b/.gitignore @@ -124,7 +124,6 @@ buck-out/ /infer/annotations/annot_classes/ /infer/annotations/annotations.jar /infer/annotations/processor_classes/ -/infer/lib/java/processor.jar infer/src/.project /dependencies/ocamldot/ocamldot /dependencies/ocamldot/ocamldot.ml diff --git a/examples/android_hello/app/src/main/java/infer/other/MainActivity.java b/examples/android_hello/app/src/main/java/infer/other/MainActivity.java index 7382fd133..c49beb82a 100644 --- a/examples/android_hello/app/src/main/java/infer/other/MainActivity.java +++ b/examples/android_hello/app/src/main/java/infer/other/MainActivity.java @@ -9,6 +9,7 @@ package infer.other; +import android.annotation.SuppressLint; import android.support.v7.app.ActionBarActivity; import android.os.Bundle; @@ -23,7 +24,7 @@ public class MainActivity extends ActionBarActivity { source().toString(); } - @SuppressWarnings("infer") + @SuppressLint("NULL_DEREFERENCE") void shouldNotBeReported() { source().toString(); } diff --git a/infer/annotations/Makefile b/infer/annotations/Makefile index e6deb6dda..fdd5e98ef 100644 --- a/infer/annotations/Makefile +++ b/infer/annotations/Makefile @@ -16,23 +16,15 @@ ANNOT_CLASSES = 'annot_classes' PROCESSOR_CLASSES = 'processor_classes' ANNOTATIONS_JAR = $(CWD)/annotations.jar -PROCESSOR_JAR = $(JAVA_LIB_DIR)/processor.jar -all: $(ANNOTATIONS_JAR) $(PROCESSOR_JAR) +all: $(ANNOTATIONS_JAR) $(ANNOTATIONS_JAR): $(ANNOT_SOURCES) mkdir -p $(ANNOT_CLASSES) javac -cp $(JSR_JAR) $(ANNOT_SOURCES) -d $(ANNOT_CLASSES) cd $(ANNOT_CLASSES) && jar cvf $(ANNOTATIONS_JAR) com -$(PROCESSOR_JAR): $(PROCESSOR_SOURCES) - mkdir -p $(PROCESSOR_CLASSES) - javac $(PROCESSOR_SOURCES) -cp .:$(JAVA_HOME)/lib/tools.jar -d $(PROCESSOR_CLASSES) - jar cvMf processor.jar -C resources META-INF -C $(PROCESSOR_CLASSES) com - mv processor.jar $(PROCESSOR_JAR) - clean: @rm -rf $(ANNOT_CLASSES) @rm -f $(ANNOTATIONS_JAR) @rm -rf $(PROCESSOR_CLASSES) - @rm -f $(PROCESSOR_JAR) diff --git a/infer/annotations/com/facebook/infer/annotprocess/CollectSuppressWarnings.java b/infer/annotations/com/facebook/infer/annotprocess/CollectSuppressWarnings.java deleted file mode 100644 index 8e303c0db..000000000 --- a/infer/annotations/com/facebook/infer/annotprocess/CollectSuppressWarnings.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * 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. - */ - -package com.facebook.infer.annotprocess; - -import java.io.IOException; -import java.io.PrintWriter; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.Map; -import java.util.Set; - -import javax.annotation.processing.AbstractProcessor; -import javax.annotation.processing.RoundEnvironment; -import javax.annotation.processing.SupportedAnnotationTypes; -import javax.annotation.processing.SupportedOptions; -import javax.lang.model.SourceVersion; -import javax.lang.model.element.Element; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.TypeElement; -import javax.lang.model.util.Elements; - -@SupportedOptions({ "SuppressWarningsOutputFilename" }) -@SupportedAnnotationTypes({ "java.lang.SuppressWarnings" }) -public class CollectSuppressWarnings extends AbstractProcessor { - - private static final String OUTPUT_FILENAME_OPTION = "SuppressWarningsOutputFilename"; - - // map of (classes -> methods in class). an empty set means suppress all warnings on class - public Map> mSuppressMap = new LinkedHashMap>(); - - // total number of classes/methods with a SuppressWarnings annotation - private int mNumToSuppress = 0; - - // write the methods/classes to suppress to .inferconfig-style JSON - private void exportSuppressMap() throws IOException { - - Map options = processingEnv.getOptions(); - String mOutputFilename = - Preconditions.checkNotNull(options.get(OUTPUT_FILENAME_OPTION), - "The filename should be passed from the Infer top-level script"); - - // output .inferconfig format file in JSON - try (PrintWriter out = new PrintWriter(mOutputFilename)) { - int elemCount = 0; - out.println("{ \"suppress_warnings\": ["); - for (Map.Entry> entry : mSuppressMap.entrySet()) { - String clazz = entry.getKey(); - Set methods = entry.getValue(); - if (methods.isEmpty()) { // empty set of methods means annotation is on class - JSONOutputUtils.outputClass(out, clazz, ++elemCount, mNumToSuppress); - } else { - for (String method : methods) { - JSONOutputUtils.outputMethod(out, clazz, method, ++elemCount, mNumToSuppress); - } - } - } - out.println("] }"); - } - } - - // we only care about @SuppressWarnings("null") and @SuppressWarnings("infer"); ignore otherwise - private boolean shouldProcess(SuppressWarnings annot) { - for (String value : annot.value()) { - if (value.equals("null") || value.equals("infer")) return true; - } - return false; - } - - // collect all of the SuppressWarnings annotations from the Java source files being compiled - public boolean process(Set annotations, RoundEnvironment roundEnv) { - - Elements elements = processingEnv.getElementUtils(); - for (TypeElement te : annotations) { - for (Element e : roundEnv.getElementsAnnotatedWith(te)) { - SuppressWarnings annot = e.getAnnotation(SuppressWarnings.class); - if (annot != null && shouldProcess(annot)) { - if (e instanceof TypeElement) { // class - String className = elements.getBinaryName((TypeElement) e).toString(); - mSuppressMap.put(className, Collections.EMPTY_SET); - mNumToSuppress++; - } else if (e instanceof ExecutableElement) { // method - String classname = e.getEnclosingElement().toString(); - java.util.Set suppressMethods = mSuppressMap.get(classname); - if (suppressMethods != null && suppressMethods.isEmpty()) { - // empty set means suppress warnings on all methods in class; do nothing - continue; - } - if (suppressMethods == null) { - suppressMethods = new LinkedHashSet(); - } - suppressMethods.add(e.getSimpleName().toString()); - mSuppressMap.put(classname, suppressMethods); - mNumToSuppress++; - } - } - } - } - - if (roundEnv.processingOver() && mNumToSuppress > 0) { - try { - exportSuppressMap(); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - return false; - } - - @Override - public SourceVersion getSupportedSourceVersion() { - return SourceVersion.latestSupported(); - } - -} diff --git a/infer/annotations/resources/META-INF/services/javax.annotation.processing.Processor b/infer/annotations/resources/META-INF/services/javax.annotation.processing.Processor deleted file mode 100644 index a4c881ef2..000000000 --- a/infer/annotations/resources/META-INF/services/javax.annotation.processing.Processor +++ /dev/null @@ -1 +0,0 @@ -com.facebook.infer.annotprocess.CollectSuppressWarnings diff --git a/infer/lib/python/inferlib/config.py b/infer/lib/python/inferlib/config.py index 79fbe9d50..8464123a5 100644 --- a/infer/lib/python/inferlib/config.py +++ b/infer/lib/python/inferlib/config.py @@ -34,9 +34,6 @@ LIB_DIRECTORY = os.path.join(INFER_INFER_DIRECTORY, 'lib') BIN_DIRECTORY = os.path.join(INFER_INFER_DIRECTORY, 'bin') JAVA_LIB_DIRECTORY = os.path.join(LIB_DIRECTORY, 'java') MODELS_JAR = os.path.join(JAVA_LIB_DIRECTORY, 'models.jar') -ANNOT_PROCESSOR_JAR = os.path.join(JAVA_LIB_DIRECTORY, 'processor.jar') -ANNOT_PROCESSOR_NAMES = \ - 'com.facebook.infer.annotprocess.CollectSuppressWarnings' WRAPPERS_DIRECTORY = os.path.join(LIB_DIRECTORY, 'wrappers') XCODE_WRAPPERS_DIRECTORY = os.path.join(LIB_DIRECTORY, 'xcode_wrappers') @@ -58,8 +55,6 @@ LOG_FILE = 'toplevel.log' BUCK_INFER_OUT = 'infer' -SUPRESS_WARNINGS_OUTPUT_FILENAME_OPTION = 'SuppressWarningsOutputFilename' - # list of possible analyzers ANALYZER_INFER = 'infer' diff --git a/infer/lib/python/inferlib/jwlib.py b/infer/lib/python/inferlib/jwlib.py index 73fe1fff3..c44a99b5c 100644 --- a/infer/lib/python/inferlib/jwlib.py +++ b/infer/lib/python/inferlib/jwlib.py @@ -26,11 +26,7 @@ parser = argparse.ArgumentParser() current_directory = utils.decode(os.getcwd()) parser.add_argument('-version', action='store_true') -parser.add_argument('-cp', '-classpath', type=utils.decode, - dest='classpath', default=os.getcwd()) parser.add_argument('-d', dest='classes_out', default=current_directory) -parser.add_argument('-processorpath', type=utils.decode, dest='processorpath') -parser.add_argument('-processor', type=utils.decode, dest='processor') def _get_javac_args(args): @@ -62,26 +58,6 @@ def create_infer_command(args, javac_arguments): ) -# return True if string is empty or an escaped variant of empty -def _is_empty_classpath(string): - stripped = string.strip("'").strip('"') - if stripped == '': - return True - elif stripped == string: - return False - else: - return _is_empty_classpath(stripped) - - -class AnnotationProcessorNotFound(Exception): - - def __init__(self, path): - self.path = path - - def __str__(self): - return repr(self.path + ' not found') - - class CompilerCall(object): def __init__(self, javac_cmd, arguments): @@ -103,85 +79,11 @@ class CompilerCall(object): else: javac_args = ['-verbose', '-g'] - if not os.path.isfile(config.ANNOT_PROCESSOR_JAR): - raise AnnotationProcessorNotFound(config.ANNOT_PROCESSOR_JAR) if self.args.classes_out is not None: javac_args += ['-d', self.args.classes_out] - classpath = self.args.classpath - # the -processorpath option precludes searching the classpath for - # annotation processors, so we don't want to use it unless the - # javac command does - if self.args.processorpath is not None: - processorpath = os.pathsep.join([config.ANNOT_PROCESSOR_JAR, - self.args.processorpath]) - javac_args += ['-processorpath', processorpath] - else: - classpath = os.pathsep.join([config.ANNOT_PROCESSOR_JAR, - classpath]) - - at_args = [ - arg for arg in self.remaining_args if arg.startswith('@')] - found_classpath = False - for at_arg in at_args: - # remove @ character - args_file_name = at_arg[1:] - with codecs.open(args_file_name, 'r', - encoding=config.CODESET) as args_file: - args_file_contents = args_file.read() - prefix_suffix = args_file_contents.split('-classpath\n', 1) - if len(prefix_suffix) == 2: - prefix, suffix = prefix_suffix - with tempfile.NamedTemporaryFile( - dir=self.args.infer_out, - suffix='_cp', - delete=False) as args_file_cp: - cp_line, _, after_cp = suffix.partition('\n') - # avoid errors the happen when we get -classpath '"', - # -classpath '', or similar from the args file - if _is_empty_classpath(cp_line): - cp_line = '\n' - else: - cp_line = ':{}\n'.format(cp_line) - cp_line = prefix + '-classpath\n' + classpath + cp_line - cp_line += after_cp - args_file_cp.write(cp_line) - at_arg_cp = '@' + args_file_cp.name - self.remaining_args = [ - at_arg_cp if arg == at_arg else arg - for arg in self.remaining_args] - found_classpath = True - break - javac_args += self.remaining_args - if not found_classpath: - # -classpath option not found in any args file - javac_args += ['-classpath', classpath] - - # this overrides the default mechanism for discovering annotation - # processors (checking the manifest of the annotation processor - # JAR), so we don't want to use it unless the javac command does - if self.args.processor is not None: - processor = '{infer_processors},{original_processors}'.format( - infer_processors=config.ANNOT_PROCESSOR_NAMES, - original_processors=self.args.processor - ) - javac_args += ['-processor', processor] - - with tempfile.NamedTemporaryFile( - mode='w', - suffix='.out', - prefix='annotations_', - delete=False) as annot_out: - # Initialize the contents of the file to a valid empty - # json object. - annot_out.write('{}') - self.suppress_warnings_out = annot_out.name - javac_args += ['-A%s=%s' % - (config.SUPRESS_WARNINGS_OUTPUT_FILENAME_OPTION, - self.suppress_warnings_out)] - def arg_must_go_on_cli(arg): # as mandated by javac, argument files must not contain # arguments @@ -281,7 +183,6 @@ class AnalyzerWithFrontendWrapper(analyze.AnalyzerWrapper): infer_cmd += [ '-verbose_out', self.javac.verbose_out, - '-suppress_warnings_out', self.javac.suppress_warnings_out, ] if self.args.debug: @@ -304,7 +205,6 @@ class AnalyzerWithFrontendWrapper(analyze.AnalyzerWrapper): def _close(self): os.remove(self.javac.verbose_out) - os.remove(self.javac.suppress_warnings_out) class AnalyzerWithJavac(AnalyzerWithFrontendWrapper): diff --git a/infer/src/backend/inferconfig.ml b/infer/src/backend/inferconfig.ml index cef942b07..49dd968ac 100644 --- a/infer/src/backend/inferconfig.ml +++ b/infer/src/backend/inferconfig.ml @@ -310,33 +310,6 @@ let never_return_null_matcher = let skip_translation_matcher = FileOrProcMatcher.load_matcher (patterns_of_json_with_key Config.patterns_skip_translation) -let suppress_warnings_matcher = - let error msg = - F.eprintf - "There was an issue reading the option %s.@\n\ - If you did not call %s directly, this is likely a bug in Infer.@\n\ - %s@." - Config.suppress_warnings_annotations_long - (Filename.basename Sys.executable_name) - msg ; - [] in - let patterns = - match Config.suppress_warnings_out with - | Some path -> ( - match Utils.read_optional_json_file path with - | Ok json -> ( - let json_key = "suppress_warnings" in - match Yojson.Basic.Util.member json_key json with - | `Null -> [] - | json -> patterns_of_json_with_key (json_key, json)) - | Error msg -> error ("Could not read or parse the supplied " ^ path ^ ":\n" ^ msg) - ) - | None when Config.current_exe <> CLOpt.Java -> [] - | None when Option.is_some Config.generated_classes -> [] - | None -> - error ("The option " ^ Config.suppress_warnings_annotations_long ^ " was not provided") in - FileOrProcMatcher.load_matcher patterns - let load_filters analyzer = { whitelist = Config.analysis_path_regex_whitelist analyzer; diff --git a/infer/src/backend/inferconfig.mli b/infer/src/backend/inferconfig.mli index ccb899d53..da02485af 100644 --- a/infer/src/backend/inferconfig.mli +++ b/infer/src/backend/inferconfig.mli @@ -32,7 +32,6 @@ val do_not_filter : filters val create_filters : Config.analyzer -> filters val never_return_null_matcher : SourceFile.t -> Procname.t -> bool -val suppress_warnings_matcher : SourceFile.t -> Procname.t -> bool val skip_translation_matcher : SourceFile.t -> Procname.t -> bool val modeled_expensive_matcher : (string -> bool) -> Procname.t -> bool diff --git a/infer/src/backend/reporting.ml b/infer/src/backend/reporting.ml index 167e3bddd..5e631cfd7 100644 --- a/infer/src/backend/reporting.ml +++ b/infer/src/backend/reporting.ml @@ -52,14 +52,14 @@ let log_issue ?session ?ltr exn = - let should_suppress_warnings summary = + let should_suppress_lint summary = !Config.curr_language = Config.Java && let annotated_signature = Annotations.get_annotated_signature summary.Specs.attributes in let ret_annotation, _ = annotated_signature.Annotations.ret in - Annotations.ia_is_suppress_warnings ret_annotation in + Annotations.ia_is_suppress_lint ret_annotation in match Specs.get_summary proc_name with - | Some summary when should_suppress_warnings summary -> () + | Some summary when should_suppress_lint summary -> () | Some summary -> let err_log = summary.Specs.attributes.ProcAttributes.err_log in log_issue_from_errlog err_kind err_log ?loc ?node_id ?session ?ltr exn diff --git a/infer/src/base/Config.ml b/infer/src/base/Config.ml index 05616e2b2..72799fcf7 100644 --- a/infer/src/base/Config.ml +++ b/infer/src/base/Config.ml @@ -183,8 +183,6 @@ let specs_files_suffix = ".specs" let start_filename = ".start" -let suppress_warnings_annotations_long = "suppress-warnings-annotations" - (** If true performs taint analysis *) let taint_analysis = true @@ -1123,11 +1121,6 @@ and subtype_multirange = CLOpt.mk_bool ~deprecated:["subtype_multirange"] ~long:"subtype-multirange" ~default:true "Use the multirange subtyping domain" -(* Path to list of collected @SuppressWarnings annotations *) -and suppress_warnings_out = - CLOpt.mk_path_opt ~deprecated:["suppress_warnings_out"] ~long:suppress_warnings_annotations_long - ~meta:"path" "" - and svg = CLOpt.mk_bool ~deprecated:["svg"] ~long:"svg" "Generate .dot and .svg files from specs" @@ -1483,7 +1476,6 @@ and stacktrace = !stacktrace and stacktraces_dir = !stacktraces_dir and stats_mode = !stats and subtype_multirange = !subtype_multirange -and suppress_warnings_out = !suppress_warnings_out and svg = !svg and symops_per_iteration = !symops_per_iteration and test = !test diff --git a/infer/src/base/Config.mli b/infer/src/base/Config.mli index f6a73470d..9a02800e1 100644 --- a/infer/src/base/Config.mli +++ b/infer/src/base/Config.mli @@ -107,7 +107,6 @@ val sources : string list val sourcepath : string option val specs_dir_name : string val specs_files_suffix : string -val suppress_warnings_annotations_long : string val start_filename : string val taint_analysis : bool val trace_absarray : bool @@ -249,7 +248,6 @@ val stacktrace : string option val stacktraces_dir : string option val stats_mode : bool val subtype_multirange : bool -val suppress_warnings_out : string option val svg : bool val symops_per_iteration : int option val test : bool diff --git a/infer/src/checkers/annotations.ml b/infer/src/checkers/annotations.ml index 8a758b7ca..93fa6bf7c 100644 --- a/infer/src/checkers/annotations.ml +++ b/infer/src/checkers/annotations.ml @@ -106,7 +106,6 @@ let performance_critical = "PerformanceCritical" let no_allocation = "NoAllocation" let ignore_allocations = "IgnoreAllocations" -let suppress_warnings = "SuppressWarnings" let suppress_lint = "SuppressLint" let privacy_source = "PrivacySource" let privacy_sink = "PrivacySink" @@ -193,8 +192,8 @@ let ia_is_no_allocation ia = let ia_is_ignore_allocations ia = ia_ends_with ia ignore_allocations -let ia_is_suppress_warnings ia = - ia_ends_with ia suppress_warnings +let ia_is_suppress_lint ia = + ia_ends_with ia suppress_lint let ia_is_privacy_source ia = ia_ends_with ia privacy_source diff --git a/infer/src/checkers/annotations.mli b/infer/src/checkers/annotations.mli index 202096fb1..db34194ff 100644 --- a/infer/src/checkers/annotations.mli +++ b/infer/src/checkers/annotations.mli @@ -17,7 +17,6 @@ val expensive : string val performance_critical : string val no_allocation : string val on_bind : string -val suppress_warnings : string type annotation = | Nullable @@ -88,7 +87,7 @@ val ia_is_expensive : Annot.Item.t -> bool val ia_is_performance_critical : Annot.Item.t -> bool val ia_is_no_allocation : Annot.Item.t -> bool val ia_is_ignore_allocations : Annot.Item.t -> bool -val ia_is_suppress_warnings : Annot.Item.t -> bool +val ia_is_suppress_lint : Annot.Item.t -> bool val ia_is_privacy_source : Annot.Item.t -> bool val ia_is_privacy_sink : Annot.Item.t -> bool val ia_is_integrity_source : Annot.Item.t -> bool diff --git a/infer/src/java/jAnnotation.ml b/infer/src/java/jAnnotation.ml index 00b653d4b..8ba1fcd5b 100644 --- a/infer/src/java/jAnnotation.ml +++ b/infer/src/java/jAnnotation.ml @@ -13,15 +13,6 @@ open! IStd open Javalib_pack -let is_suppress_warnings_annotated = - Inferconfig.suppress_warnings_matcher SourceFile.empty - -let suppress_warnings = - ({ Annot. - class_name = Annotations.suppress_warnings; - parameters = ["infer"] }, - true) - (** Translate an annotation. *) let translate a : Annot.t = let class_name = JBasics.cn_name a.JBasics.kind in @@ -48,13 +39,9 @@ let translate_item avlist : Annot.Item.t = (** Translate a method annotation. *) -let translate_method proc_name ann : Annot.Method.t = +let translate_method ann : Annot.Method.t = let global_ann = ann.Javalib.ma_global in let param_ann = ann.Javalib.ma_parameters in - let ret_item = - let base_annotations = translate_item global_ann in - if is_suppress_warnings_annotated proc_name then - suppress_warnings :: base_annotations - else base_annotations in + let ret_item = translate_item global_ann in let param_items = IList.map translate_item param_ann in ret_item, param_items diff --git a/infer/src/java/jAnnotation.mli b/infer/src/java/jAnnotation.mli index ceddf8786..b811264f1 100644 --- a/infer/src/java/jAnnotation.mli +++ b/infer/src/java/jAnnotation.mli @@ -17,4 +17,4 @@ open Javalib_pack val translate_item : (JBasics.annotation * Javalib.visibility) list -> Annot.Item.t (** Translate a method annotation. *) -val translate_method : Procname.t -> Javalib.method_annotations -> Annot.Method.t +val translate_method : Javalib.method_annotations -> Annot.Method.t diff --git a/infer/src/java/jTrans.ml b/infer/src/java/jTrans.ml index 8ed0b1871..5941d6f83 100644 --- a/infer/src/java/jTrans.ml +++ b/infer/src/java/jTrans.ml @@ -174,8 +174,8 @@ let translate_locals program tenv formals bytecode jbir_code = let with_jbir_vars = Array.fold ~f:(fun accu jbir_var -> - let var = Mangled.from_string (JBir.var_name_g jbir_var) in - collect accu (var, Typ.Tvoid)) + let var = Mangled.from_string (JBir.var_name_g jbir_var) in + collect accu (var, Typ.Tvoid)) ~init:with_bytecode_vars (JBir.vars jbir_code) in snd with_jbir_vars @@ -246,10 +246,10 @@ let get_implementation cm = let c_code = Array.map ~f:(function - | (JCode.OpInvoke (`Dynamic _, ms)) -> - JCode.OpInvoke (`Static JBasics.java_lang_object, ms) - | opcode -> - opcode) + | (JCode.OpInvoke (`Dynamic _, ms)) -> + JCode.OpInvoke (`Static JBasics.java_lang_object, ms) + | opcode -> + opcode) bytecode.JCode.c_code in let hacked_bytecode = { bytecode with JCode.c_code; } in let jbir_code = @@ -281,7 +281,7 @@ let create_am_procdesc program icfg am proc_name : Procdesc.t = let formals = formals_from_signature program tenv cn ms (JTransType.get_method_kind m) in let method_annotation = - JAnnotation.translate_method proc_name am.Javalib.am_annotations in + JAnnotation.translate_method am.Javalib.am_annotations in let procdesc = let proc_attributes = { (ProcAttributes.default proc_name Config.Java) with @@ -313,7 +313,7 @@ let create_native_procdesc program icfg cm proc_name = let formals = formals_from_signature program tenv cn ms (JTransType.get_method_kind m) in let method_annotation = - JAnnotation.translate_method proc_name cm.Javalib.cm_annotations in + JAnnotation.translate_method cm.Javalib.cm_annotations in let proc_attributes = { (ProcAttributes.default proc_name Config.Java) with ProcAttributes.access = trans_access cm.Javalib.cm_access; @@ -343,7 +343,7 @@ let create_cm_procdesc source_file program linereader icfg cm proc_name = let loc_exit = get_location source_file jbir_code (Array.length (JBir.code jbir_code) - 1) in let method_annotation = - JAnnotation.translate_method proc_name cm.Javalib.cm_annotations in + JAnnotation.translate_method cm.Javalib.cm_annotations in update_constr_loc cn ms loc_start; update_init_loc cn ms loc_exit; let proc_attributes = diff --git a/infer/tests/build_systems/ant/issues.exp b/infer/tests/build_systems/ant/issues.exp index 3254402d4..a9ebf2a58 100644 --- a/infer/tests/build_systems/ant/issues.exp +++ b/infer/tests/build_systems/ant/issues.exp @@ -56,7 +56,6 @@ codetoanalyze/java/infer/GuardedByExample.java, void GuardedByExample.guardedByT codetoanalyze/java/infer/GuardedByExample.java, void GuardedByExample.guardedByTypeSyntaxBad(), 2, UNSAFE_GUARDED_BY_ACCESS, [start of procedure guardedByTypeSyntaxBad()] codetoanalyze/java/infer/GuardedByExample.java, void GuardedByExample.readFAfterBlockBad(), 3, UNSAFE_GUARDED_BY_ACCESS, [start of procedure readFAfterBlockBad()] codetoanalyze/java/infer/GuardedByExample.java, void GuardedByExample.readFBad(), 1, UNSAFE_GUARDED_BY_ACCESS, [start of procedure readFBad()] -codetoanalyze/java/infer/GuardedByExample.java, void GuardedByExample.readFBadButSuppressedOther(), 1, UNSAFE_GUARDED_BY_ACCESS, [start of procedure readFBadButSuppressedOther()] codetoanalyze/java/infer/GuardedByExample.java, void GuardedByExample.readFBadWrongAnnotation(), 1, UNSAFE_GUARDED_BY_ACCESS, [start of procedure readFBadWrongAnnotation()] codetoanalyze/java/infer/GuardedByExample.java, void GuardedByExample.readFBadWrongLock(), 2, UNSAFE_GUARDED_BY_ACCESS, [start of procedure readFBadWrongLock()] codetoanalyze/java/infer/GuardedByExample.java, void GuardedByExample.readHBad(), 2, UNSAFE_GUARDED_BY_ACCESS, [start of procedure readHBad()] diff --git a/infer/tests/build_systems/buck/issues.exp b/infer/tests/build_systems/buck/issues.exp index 5caf8f9cb..dbde139dd 100644 --- a/infer/tests/build_systems/buck/issues.exp +++ b/infer/tests/build_systems/buck/issues.exp @@ -56,7 +56,6 @@ infer/tests/codetoanalyze/java/infer/GuardedByExample.java, void GuardedByExampl infer/tests/codetoanalyze/java/infer/GuardedByExample.java, void GuardedByExample.guardedByTypeSyntaxBad(), 2, UNSAFE_GUARDED_BY_ACCESS, [start of procedure guardedByTypeSyntaxBad()] infer/tests/codetoanalyze/java/infer/GuardedByExample.java, void GuardedByExample.readFAfterBlockBad(), 3, UNSAFE_GUARDED_BY_ACCESS, [start of procedure readFAfterBlockBad()] infer/tests/codetoanalyze/java/infer/GuardedByExample.java, void GuardedByExample.readFBad(), 1, UNSAFE_GUARDED_BY_ACCESS, [start of procedure readFBad()] -infer/tests/codetoanalyze/java/infer/GuardedByExample.java, void GuardedByExample.readFBadButSuppressedOther(), 1, UNSAFE_GUARDED_BY_ACCESS, [start of procedure readFBadButSuppressedOther()] infer/tests/codetoanalyze/java/infer/GuardedByExample.java, void GuardedByExample.readFBadWrongAnnotation(), 1, UNSAFE_GUARDED_BY_ACCESS, [start of procedure readFBadWrongAnnotation()] infer/tests/codetoanalyze/java/infer/GuardedByExample.java, void GuardedByExample.readFBadWrongLock(), 2, UNSAFE_GUARDED_BY_ACCESS, [start of procedure readFBadWrongLock()] infer/tests/codetoanalyze/java/infer/GuardedByExample.java, void GuardedByExample.readHBad(), 2, UNSAFE_GUARDED_BY_ACCESS, [start of procedure readHBad()] diff --git a/infer/tests/codetoanalyze/java/checkers/ExpensiveInheritanceExample.java b/infer/tests/codetoanalyze/java/checkers/ExpensiveInheritanceExample.java index 2129b8a10..18244368f 100644 --- a/infer/tests/codetoanalyze/java/checkers/ExpensiveInheritanceExample.java +++ b/infer/tests/codetoanalyze/java/checkers/ExpensiveInheritanceExample.java @@ -9,6 +9,8 @@ package codetoanalyze.java.checkers; +import android.annotation.SuppressLint; + import com.facebook.infer.annotation.Expensive; import com.facebook.infer.annotation.PerformanceCritical; @@ -18,7 +20,7 @@ interface I { class A implements I { - @SuppressWarnings("infer") + @SuppressLint("CHECKERS_EXPENSIVE_OVERRIDES_UNANNOTATED") // Suppressing the sub-typing violation warning here as foo() is not annotated as @Expensive // in the interface. This report is legit but is not relevant for the current test. @Expensive diff --git a/infer/tests/codetoanalyze/java/checkers/issues.exp b/infer/tests/codetoanalyze/java/checkers/issues.exp index 455334b13..87e2c6016 100644 --- a/infer/tests/codetoanalyze/java/checkers/issues.exp +++ b/infer/tests/codetoanalyze/java/checkers/issues.exp @@ -29,7 +29,6 @@ codetoanalyze/java/checkers/ImmutableCast.java, List ImmutableCast.badCastFromFi codetoanalyze/java/checkers/NoAllocationExample.java, void NoAllocationExample.directlyAllocatingMethod(), 1, CHECKERS_ALLOCATES_MEMORY, [] codetoanalyze/java/checkers/NoAllocationExample.java, void NoAllocationExample.indirectlyAllocatingMethod(), 1, CHECKERS_ALLOCATES_MEMORY, [] codetoanalyze/java/checkers/PrintfArgsChecker.java, void PrintfArgsChecker.formatStringIsNotLiteral(PrintStream), 2, CHECKERS_PRINTF_ARGS, [Format string must be string literal] -codetoanalyze/java/checkers/PrintfArgsChecker.java, void PrintfArgsChecker.notSuppressed(PrintStream), 1, CHECKERS_PRINTF_ARGS, [printf(...) at line 36: parameter 2 is expected to be of type java.lang.Integer but java.lang.String was given.] codetoanalyze/java/checkers/PrintfArgsChecker.java, void PrintfArgsChecker.stringInsteadOfInteger(PrintStream), 1, CHECKERS_PRINTF_ARGS, [printf(...) at line 40: parameter 2 is expected to be of type java.lang.Integer but java.lang.String was given.] codetoanalyze/java/checkers/PrintfArgsChecker.java, void PrintfArgsChecker.wrongNumberOfArguments(PrintStream), 1, CHECKERS_PRINTF_ARGS, [format string arguments don't mach provided arguments in printf(...) at line 44] codetoanalyze/java/checkers/TwoCheckersExample.java, List TwoCheckersExample.shouldRaiseImmutableCastError(), 0, CHECKERS_IMMUTABLE_CAST, [Method shouldRaiseImmutableCastError() returns class com.google.common.collect.ImmutableList but the return type is class java.util.List. Make sure that users of this method do not try to modify the collection.] diff --git a/infer/tests/codetoanalyze/java/eradicate/SuppressWarningsExample.java b/infer/tests/codetoanalyze/java/eradicate/SuppressWarningsExample.java deleted file mode 100644 index a6ca69493..000000000 --- a/infer/tests/codetoanalyze/java/eradicate/SuppressWarningsExample.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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. - */ - -package codetoanalyze.java.eradicate; - -import java.lang.SuppressWarnings; - -import javax.annotation.Nullable; - -public class SuppressWarningsExample { - - @SuppressWarnings("null") - static class DoSuppress { - - @Nullable Object mFld; - - void doSuppress1(@Nullable Object o) { - o.toString(); - } - - void doSuppress2() { - mFld.toString(); - } - } - - @SuppressWarnings("null") - public void doSuppress(@Nullable Object o) { - o.toString(); - } - - @SuppressWarnings("infer") - public void doSuppressInferAnnot(@Nullable Object o) { - o.toString(); - } - - @SuppressWarnings("unchecked") - public void doNotSuppressWrongAnnot(@Nullable Object o) { - o.toString(); - } - - public void doNotSuppressNoAnnot(@Nullable Object o) { - o.toString(); - } - -} diff --git a/infer/tests/codetoanalyze/java/eradicate/issues.exp b/infer/tests/codetoanalyze/java/eradicate/issues.exp index 6aa9d6c4a..d67f770d6 100644 --- a/infer/tests/codetoanalyze/java/eradicate/issues.exp +++ b/infer/tests/codetoanalyze/java/eradicate/issues.exp @@ -47,5 +47,3 @@ codetoanalyze/java/eradicate/ReturnNotNullable.java, String ReturnNotNullable.re codetoanalyze/java/eradicate/ReturnNotNullable.java, String ReturnNotNullable.return_null_in_catch(), 0, ERADICATE_RETURN_NOT_NULLABLE, [origin,Method `return_null_in_catch()` may return null but it is not annotated with `@Nullable`. (Origin: null constant at line 110)] codetoanalyze/java/eradicate/ReturnNotNullable.java, String ReturnNotNullable.return_null_in_catch_after_throw(), 0, ERADICATE_RETURN_NOT_NULLABLE, [origin,Method `return_null_in_catch_after_throw()` may return null but it is not annotated with `@Nullable`. (Origin: null constant at line 122)] codetoanalyze/java/eradicate/ReturnNotNullable.java, URL ReturnNotNullable.getResourceNullable(Class,String), 0, ERADICATE_RETURN_NOT_NULLABLE, [origin,Method `getResourceNullable(...)` may return null but it is not annotated with `@Nullable`. (Origin: call to getResource(...) modelled in eradicate/modelTables.ml at line 127)] -codetoanalyze/java/eradicate/SuppressWarningsExample.java, void SuppressWarningsExample.doNotSuppressNoAnnot(Object), 1, ERADICATE_NULL_METHOD_CALL, [The value of `o` in the call to `toString()` could be null. (Origin: method parameter o)] -codetoanalyze/java/eradicate/SuppressWarningsExample.java, void SuppressWarningsExample.doNotSuppressWrongAnnot(Object), 1, ERADICATE_NULL_METHOD_CALL, [The value of `o` in the call to `toString()` could be null. (Origin: method parameter o)] diff --git a/infer/tests/codetoanalyze/java/infer/NullPointerExceptions.java b/infer/tests/codetoanalyze/java/infer/NullPointerExceptions.java index dc4acce30..47fb1727e 100644 --- a/infer/tests/codetoanalyze/java/infer/NullPointerExceptions.java +++ b/infer/tests/codetoanalyze/java/infer/NullPointerExceptions.java @@ -9,6 +9,7 @@ package codetoanalyze.java.infer; +import android.annotation.SuppressLint; import android.content.ContentResolver; import android.content.Context; import android.database.Cursor; @@ -479,7 +480,7 @@ public class NullPointerExceptions { derefUndefinedCallee().toString(); } - @SuppressWarnings("null") // TODO(#8647398): Add support for @SuppressWarnings with Ant + @SuppressLint("NULL_DEREFERENCE") void shouldNotReportNPE() { Object o = null; o.toString(); diff --git a/infer/tests/codetoanalyze/java/infer/issues.exp b/infer/tests/codetoanalyze/java/infer/issues.exp index ee2670a41..eeb9e40c8 100644 --- a/infer/tests/codetoanalyze/java/infer/issues.exp +++ b/infer/tests/codetoanalyze/java/infer/issues.exp @@ -121,7 +121,6 @@ codetoanalyze/java/infer/GuardedByExample.java, void GuardedByExample.guardedByT codetoanalyze/java/infer/GuardedByExample.java, void GuardedByExample.guardedByTypeSyntaxBad(), 2, UNSAFE_GUARDED_BY_ACCESS, [start of procedure guardedByTypeSyntaxBad()] codetoanalyze/java/infer/GuardedByExample.java, void GuardedByExample.readFAfterBlockBad(), 3, UNSAFE_GUARDED_BY_ACCESS, [start of procedure readFAfterBlockBad()] codetoanalyze/java/infer/GuardedByExample.java, void GuardedByExample.readFBad(), 1, UNSAFE_GUARDED_BY_ACCESS, [start of procedure readFBad()] -codetoanalyze/java/infer/GuardedByExample.java, void GuardedByExample.readFBadButSuppressedOther(), 1, UNSAFE_GUARDED_BY_ACCESS, [start of procedure readFBadButSuppressedOther()] codetoanalyze/java/infer/GuardedByExample.java, void GuardedByExample.readFBadWrongAnnotation(), 1, UNSAFE_GUARDED_BY_ACCESS, [start of procedure readFBadWrongAnnotation()] codetoanalyze/java/infer/GuardedByExample.java, void GuardedByExample.readFBadWrongLock(), 2, UNSAFE_GUARDED_BY_ACCESS, [start of procedure readFBadWrongLock()] codetoanalyze/java/infer/GuardedByExample.java, void GuardedByExample.readHBad(), 2, UNSAFE_GUARDED_BY_ACCESS, [start of procedure readHBad()]