diff --git a/infer/tests/build_systems/buck/.buckconfig b/infer/tests/build_systems/buck/.buckconfig new file mode 100644 index 000000000..250f76f47 --- /dev/null +++ b/infer/tests/build_systems/buck/.buckconfig @@ -0,0 +1,9 @@ +[buildfile] + includes = //DEFS + +[project] + ignore = .git, .ml, .mli + +[java] + source_level = 8 + target_level = 8 \ No newline at end of file diff --git a/infer/tests/build_systems/buck/.buckversion b/infer/tests/build_systems/buck/.buckversion new file mode 120000 index 000000000..0a46cf46a --- /dev/null +++ b/infer/tests/build_systems/buck/.buckversion @@ -0,0 +1 @@ +../../../../.buckversion \ No newline at end of file diff --git a/DEFS b/infer/tests/build_systems/buck/DEFS similarity index 100% rename from DEFS rename to infer/tests/build_systems/buck/DEFS diff --git a/infer/tests/build_systems/buck/Makefile b/infer/tests/build_systems/buck/Makefile index 4863ff554..709094427 100644 --- a/infer/tests/build_systems/buck/Makefile +++ b/infer/tests/build_systems/buck/Makefile @@ -4,28 +4,20 @@ # LICENSE file in the root directory of this source tree. TESTS_DIR = ../.. -ROOT_DIR = $(TESTS_DIR)/../.. -BUCK_TARGET = //infer/tests/build_systems/genrule/module2:module2 -SOURCES = $(wildcard $(TESTS_DIR)/codetoanalyze/java/infer/*.java) -OBJECTS = $(ROOT_DIR)/buck-out/gen/infer/tests/build_systems/genrule/module2/lib__module2__output/module2.jar +BUCK_TARGET = //module2:module2 INFER_OPTIONS = --eradicate --no-linters -INFERPRINT_OPTIONS = --project-root $(ROOT_DIR) --issues-tests -CLEAN_EXTRA = $(ROOT_DIR)/buck-out +INFERPRINT_OPTIONS = --issues-tests +CLEAN_EXTRA = buck-out +SOURCES = $(shell find . -name '*.java') + include $(TESTS_DIR)/java.make include $(TESTS_DIR)/infer.make -$(OBJECTS): $(JAVA_SOURCE_FILES) - $(QUIET)cd $(ROOT_DIR) && \ - $(call silent_on_success,Compiling Buck Java tests,\ - INFER_BIN=$(INFER_BIN) \ - $(TESTLOCK) $(BUCK) build --deep --no-cache $(BUCK_TARGET)) - -infer-out/report.json: $(JAVA_DEPS) $(JAVA_SOURCE_FILES) - $(QUIET)cd $(ROOT_DIR) && \ - $(TESTLOCK) $(REMOVE_DIR) buck-out && \ +infer-out/report.json: $(JAVA_DEPS) $(SOURCES) + $(QUIET)$(REMOVE_DIR) buck-out && \ $(call silent_on_success,Testing Buck Java integration,\ INFER_BIN=$(INFER_BIN) \ - $(TESTLOCK) $(INFER_BIN) $(INFER_OPTIONS) --results-dir $(CURDIR)/infer-out -- \ + $(INFER_BIN) $(INFER_OPTIONS) --results-dir $(CURDIR)/infer-out -- \ $(BUCK) build --deep --no-cache $(BUCK_TARGET)) diff --git a/infer/tests/build_systems/buck/annotations/BUCK b/infer/tests/build_systems/buck/annotations/BUCK new file mode 100644 index 000000000..bc0b50a7f --- /dev/null +++ b/infer/tests/build_systems/buck/annotations/BUCK @@ -0,0 +1,7 @@ +java_library( + name='annotations', + srcs=['Nullable.java'], + visibility=[ + 'PUBLIC' + ], +) diff --git a/infer/tests/build_systems/buck/annotations/Nullable.java b/infer/tests/build_systems/buck/annotations/Nullable.java new file mode 100644 index 000000000..429589abb --- /dev/null +++ b/infer/tests/build_systems/buck/annotations/Nullable.java @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2018-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +package genrule.annotations; + +public @interface Nullable {} diff --git a/infer/tests/build_systems/buck/issues.exp b/infer/tests/build_systems/buck/issues.exp index fb7ad959a..c080e6b9b 100644 --- a/infer/tests/build_systems/buck/issues.exp +++ b/infer/tests/build_systems/buck/issues.exp @@ -1,22 +1,22 @@ -infer/tests/build_systems/genrule/module1/Class1.java, genrule.module1.Class1.localNPE1():void, 2, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [The value of `obj` in the call to `toString()` is nullable and is not locally checked for null. (Origin: null constant at line 24)] -infer/tests/build_systems/genrule/module1/Class1.java, genrule.module1.Class1.localNPE1():void, 2, NULL_DEREFERENCE, no_bucket, ERROR, [start of procedure localNPE1()] -infer/tests/build_systems/genrule/module1/Class1.java, genrule.module1.Class1.unannotatedReturnNull():java.lang.Object, 0, ERADICATE_RETURN_NOT_NULLABLE, no_bucket, WARNING, [Method `unannotatedReturnNull()` may return null but it is not annotated with `@Nullable`. (Origin: null constant at line 33)] -infer/tests/build_systems/genrule/module2/Class2.java, genrule.module2.Class2$Sub.subtypingInconsistency(java.lang.Object):java.lang.Object, 0, ERADICATE_INCONSISTENT_SUBCLASS_PARAMETER_ANNOTATION, no_bucket, WARNING, [First parameter `object` of method `Class2$Sub.subtypingInconsistency(...)` is not `@Nullable` but is declared `@Nullable`in the parent class method `Class1$Sub.subtypingInconsistency(...)`.] -infer/tests/build_systems/genrule/module2/Class2.java, genrule.module2.Class2$Sub.subtypingInconsistency(java.lang.Object):java.lang.Object, 0, ERADICATE_INCONSISTENT_SUBCLASS_RETURN_ANNOTATION, no_bucket, WARNING, [Method `Class2$Sub.subtypingInconsistency(...)` is annotated with `@Nullable` but overrides unannotated method `Class1$Sub.subtypingInconsistency(...)`.] -infer/tests/build_systems/genrule/module2/Class2.java, genrule.module2.Class2.dereferenceInterTargetField1Bad(genrule.module1.Class1):void, 1, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [The value of `class1.field1` in the call to `toString()` is nullable and is not locally checked for null. (Origin: field Class1.field1 at line 53)] -infer/tests/build_systems/genrule/module2/Class2.java, genrule.module2.Class2.dereferenceInterTargetField1Bad(genrule.module1.Class1):void, 1, NULL_DEREFERENCE, no_bucket, ERROR, [start of procedure dereferenceInterTargetField1Bad(...)] -infer/tests/build_systems/genrule/module2/Class2.java, genrule.module2.Class2.dereferenceInterTargetField2Bad(genrule.module1.Class1):int, 1, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [Object `class1.field2` is nullable and is not locally checked for null when accessing field `Class1.x`. (Origin: field Class1.field2 at line 57)] -infer/tests/build_systems/genrule/module2/Class2.java, genrule.module2.Class2.dereferenceInterTargetField2Bad(genrule.module1.Class1):int, 1, NULL_DEREFERENCE, no_bucket, ERROR, [start of procedure dereferenceInterTargetField2Bad(...)] -infer/tests/build_systems/genrule/module2/Class2.java, genrule.module2.Class2.dereferenceLocalNullableFieldBad():void, 1, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [The value of `Class2.field` in the call to `toString()` is nullable and is not locally checked for null. (Origin: field Class2.field at line 49)] -infer/tests/build_systems/genrule/module2/Class2.java, genrule.module2.Class2.dereferenceLocalNullableFieldBad():void, 1, NULL_DEREFERENCE, no_bucket, ERROR, [start of procedure dereferenceLocalNullableFieldBad()] -infer/tests/build_systems/genrule/module2/Class2.java, genrule.module2.Class2.dereferenceUnannotatedMethodReturningNullBad(genrule.module1.Class1):void, 1, NULL_DEREFERENCE, no_bucket, ERROR, [start of procedure dereferenceUnannotatedMethodReturningNullBad(...),start of procedure unannotatedReturnNull(),return from a call to Object Class1.unannotatedReturnNull()] -infer/tests/build_systems/genrule/module2/Class2.java, genrule.module2.Class2.followMethodDeclarationOnlyBad(genrule.module1.SkipImplementationClass1):void, 2, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [The value of `obj2` in the call to `toString()` is nullable and is not locally checked for null. (Origin: call to annotatedNullable() at line 39)] -infer/tests/build_systems/genrule/module2/Class2.java, genrule.module2.Class2.followMethodDeclarationOnlyBad(genrule.module1.SkipImplementationClass1):void, 2, NULL_DEREFERENCE, no_bucket, ERROR, [start of procedure followMethodDeclarationOnlyBad(...),Skipping annotatedNullable(): unknown method] -infer/tests/build_systems/genrule/module2/Class2.java, genrule.module2.Class2.interTargetAbstractNPEBad(genrule.module1.Class1):void, 2, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [The value of `obj` in the call to `toString()` is nullable and is not locally checked for null. (Origin: call to abstractMayReturnNull() at line 29)] -infer/tests/build_systems/genrule/module2/Class2.java, genrule.module2.Class2.interTargetAbstractNPEBad(genrule.module1.Class1):void, 2, NULL_DEREFERENCE, no_bucket, ERROR, [start of procedure interTargetAbstractNPEBad(...),Skipping abstractMayReturnNull(): unknown method] -infer/tests/build_systems/genrule/module2/Class2.java, genrule.module2.Class2.interTargetNPEBad():void, 2, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [The value of `obj` in the call to `toString()` is nullable and is not locally checked for null. (Origin: call to returnsNull() at line 24)] -infer/tests/build_systems/genrule/module2/Class2.java, genrule.module2.Class2.interTargetNPEBad():void, 2, NULL_DEREFERENCE, no_bucket, ERROR, [start of procedure interTargetNPEBad(),start of procedure returnsNull(),return from a call to String Class1.returnsNull()] -infer/tests/build_systems/genrule/module2/Class2.java, genrule.module2.Class2.interTargetNativeNPEBad(genrule.module1.Class1):void, 2, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [The value of `obj` in the call to `toString()` is nullable and is not locally checked for null. (Origin: call to nativeMayReturnNull() at line 34)] -infer/tests/build_systems/genrule/module2/Class2.java, genrule.module2.Class2.interTargetNativeNPEBad(genrule.module1.Class1):void, 2, NULL_DEREFERENCE, no_bucket, ERROR, [start of procedure interTargetNativeNPEBad(...),Skipping nativeMayReturnNull(): unknown method] -infer/tests/build_systems/genrule/module2/Class2.java, genrule.module2.Class2.localNPE2Bad():void, 2, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [The value of `obj` in the call to `toString()` is nullable and is not locally checked for null. (Origin: null constant at line 19)] -infer/tests/build_systems/genrule/module2/Class2.java, genrule.module2.Class2.localNPE2Bad():void, 2, NULL_DEREFERENCE, no_bucket, ERROR, [start of procedure localNPE2Bad()] +module1/Class1.java, genrule.module1.Class1.localNPE1():void, 2, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [The value of `obj` in the call to `toString()` is nullable and is not locally checked for null. (Origin: null constant at line 24)] +module1/Class1.java, genrule.module1.Class1.localNPE1():void, 2, NULL_DEREFERENCE, no_bucket, ERROR, [start of procedure localNPE1()] +module1/Class1.java, genrule.module1.Class1.unannotatedReturnNull():java.lang.Object, 0, ERADICATE_RETURN_NOT_NULLABLE, no_bucket, WARNING, [Method `unannotatedReturnNull()` may return null but it is not annotated with `@Nullable`. (Origin: null constant at line 33)] +module2/Class2.java, genrule.module2.Class2$Sub.subtypingInconsistency(java.lang.Object):java.lang.Object, 0, ERADICATE_INCONSISTENT_SUBCLASS_PARAMETER_ANNOTATION, no_bucket, WARNING, [First parameter `object` of method `Class2$Sub.subtypingInconsistency(...)` is not `@Nullable` but is declared `@Nullable`in the parent class method `Class1$Sub.subtypingInconsistency(...)`.] +module2/Class2.java, genrule.module2.Class2$Sub.subtypingInconsistency(java.lang.Object):java.lang.Object, 0, ERADICATE_INCONSISTENT_SUBCLASS_RETURN_ANNOTATION, no_bucket, WARNING, [Method `Class2$Sub.subtypingInconsistency(...)` is annotated with `@Nullable` but overrides unannotated method `Class1$Sub.subtypingInconsistency(...)`.] +module2/Class2.java, genrule.module2.Class2.dereferenceInterTargetField1Bad(genrule.module1.Class1):void, 1, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [The value of `class1.field1` in the call to `toString()` is nullable and is not locally checked for null. (Origin: field Class1.field1 at line 53)] +module2/Class2.java, genrule.module2.Class2.dereferenceInterTargetField1Bad(genrule.module1.Class1):void, 1, NULL_DEREFERENCE, no_bucket, ERROR, [start of procedure dereferenceInterTargetField1Bad(...)] +module2/Class2.java, genrule.module2.Class2.dereferenceInterTargetField2Bad(genrule.module1.Class1):int, 1, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [Object `class1.field2` is nullable and is not locally checked for null when accessing field `Class1.x`. (Origin: field Class1.field2 at line 57)] +module2/Class2.java, genrule.module2.Class2.dereferenceInterTargetField2Bad(genrule.module1.Class1):int, 1, NULL_DEREFERENCE, no_bucket, ERROR, [start of procedure dereferenceInterTargetField2Bad(...)] +module2/Class2.java, genrule.module2.Class2.dereferenceLocalNullableFieldBad():void, 1, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [The value of `Class2.field` in the call to `toString()` is nullable and is not locally checked for null. (Origin: field Class2.field at line 49)] +module2/Class2.java, genrule.module2.Class2.dereferenceLocalNullableFieldBad():void, 1, NULL_DEREFERENCE, no_bucket, ERROR, [start of procedure dereferenceLocalNullableFieldBad()] +module2/Class2.java, genrule.module2.Class2.dereferenceUnannotatedMethodReturningNullBad(genrule.module1.Class1):void, 1, NULL_DEREFERENCE, no_bucket, ERROR, [start of procedure dereferenceUnannotatedMethodReturningNullBad(...),start of procedure unannotatedReturnNull(),return from a call to Object Class1.unannotatedReturnNull()] +module2/Class2.java, genrule.module2.Class2.followMethodDeclarationOnlyBad(genrule.module1.SkipImplementationClass1):void, 2, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [The value of `obj2` in the call to `toString()` is nullable and is not locally checked for null. (Origin: call to annotatedNullable() at line 39)] +module2/Class2.java, genrule.module2.Class2.followMethodDeclarationOnlyBad(genrule.module1.SkipImplementationClass1):void, 2, NULL_DEREFERENCE, no_bucket, ERROR, [start of procedure followMethodDeclarationOnlyBad(...),Skipping annotatedNullable(): unknown method] +module2/Class2.java, genrule.module2.Class2.interTargetAbstractNPEBad(genrule.module1.Class1):void, 2, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [The value of `obj` in the call to `toString()` is nullable and is not locally checked for null. (Origin: call to abstractMayReturnNull() at line 29)] +module2/Class2.java, genrule.module2.Class2.interTargetAbstractNPEBad(genrule.module1.Class1):void, 2, NULL_DEREFERENCE, no_bucket, ERROR, [start of procedure interTargetAbstractNPEBad(...),Skipping abstractMayReturnNull(): unknown method] +module2/Class2.java, genrule.module2.Class2.interTargetNPEBad():void, 2, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [The value of `obj` in the call to `toString()` is nullable and is not locally checked for null. (Origin: call to returnsNull() at line 24)] +module2/Class2.java, genrule.module2.Class2.interTargetNPEBad():void, 2, NULL_DEREFERENCE, no_bucket, ERROR, [start of procedure interTargetNPEBad(),start of procedure returnsNull(),return from a call to String Class1.returnsNull()] +module2/Class2.java, genrule.module2.Class2.interTargetNativeNPEBad(genrule.module1.Class1):void, 2, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [The value of `obj` in the call to `toString()` is nullable and is not locally checked for null. (Origin: call to nativeMayReturnNull() at line 34)] +module2/Class2.java, genrule.module2.Class2.interTargetNativeNPEBad(genrule.module1.Class1):void, 2, NULL_DEREFERENCE, no_bucket, ERROR, [start of procedure interTargetNativeNPEBad(...),Skipping nativeMayReturnNull(): unknown method] +module2/Class2.java, genrule.module2.Class2.localNPE2Bad():void, 2, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [The value of `obj` in the call to `toString()` is nullable and is not locally checked for null. (Origin: null constant at line 19)] +module2/Class2.java, genrule.module2.Class2.localNPE2Bad():void, 2, NULL_DEREFERENCE, no_bucket, ERROR, [start of procedure localNPE2Bad()] diff --git a/infer/tests/build_systems/buck/module1/BUCK b/infer/tests/build_systems/buck/module1/BUCK new file mode 100644 index 000000000..4ac82ec7d --- /dev/null +++ b/infer/tests/build_systems/buck/module1/BUCK @@ -0,0 +1,10 @@ +java_library( + name='module1', + srcs=glob(["*.java"]), + deps=[ + '//annotations:annotations', + ], + visibility=[ + 'PUBLIC' + ], +) diff --git a/infer/tests/build_systems/buck/module1/Class1.java b/infer/tests/build_systems/buck/module1/Class1.java new file mode 100644 index 000000000..08a6b63b4 --- /dev/null +++ b/infer/tests/build_systems/buck/module1/Class1.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2017-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package genrule.module1; + +import genrule.annotations.Nullable; + +public abstract class Class1 { + + public @Nullable Object field1; + + public int x; + public @Nullable Class1 field2; + + public static @Nullable String returnsNull() { + return null; + } + + void localNPE1() { + Object obj = null; + obj.toString(); + } + + public abstract @Nullable Object abstractMayReturnNull(); + + public native @Nullable Object nativeMayReturnNull(); + + public Object unannotatedReturnNull() { + return null; + } + + public static class Sub { + public Object subtypingInconsistency(@Nullable Object object) { + return new Object(); + } + } +} diff --git a/infer/tests/build_systems/buck/module1/SkipImplementationClass1.java b/infer/tests/build_systems/buck/module1/SkipImplementationClass1.java new file mode 100644 index 000000000..e7cffcf4e --- /dev/null +++ b/infer/tests/build_systems/buck/module1/SkipImplementationClass1.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2017-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +// _SHOULD_SKIP_IMPLEMENTATION_ + +package genrule.module1; + +import genrule.annotations.Nullable; + +public class SkipImplementationClass1 { + + public @Nullable Object annotatedNullable() { + return new Object(); + } + + public Object notAnnotatedNullable() { + return null; + } +} diff --git a/infer/tests/build_systems/buck/module2/BUCK b/infer/tests/build_systems/buck/module2/BUCK new file mode 100644 index 000000000..33f3d881f --- /dev/null +++ b/infer/tests/build_systems/buck/module2/BUCK @@ -0,0 +1,8 @@ +java_library( + name='module2', + srcs=glob(["*.java"]), + deps=[ + '//module1:module1', + '//annotations:annotations', + ] +) diff --git a/infer/tests/build_systems/buck/module2/Class2.java b/infer/tests/build_systems/buck/module2/Class2.java new file mode 100644 index 000000000..a5b1dcfe1 --- /dev/null +++ b/infer/tests/build_systems/buck/module2/Class2.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2017-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package genrule.module2; + +import genrule.annotations.Nullable; +import genrule.module1.Class1; +import genrule.module1.SkipImplementationClass1; + +public class Class2 { + + @Nullable Object field; + + void localNPE2Bad() { + Object obj = null; + obj.toString(); + } + + void interTargetNPEBad() { + Object obj = Class1.returnsNull(); + obj.toString(); + } + + void interTargetAbstractNPEBad(Class1 class1) { + Object obj = class1.abstractMayReturnNull(); + obj.toString(); + } + + void interTargetNativeNPEBad(Class1 class1) { + Object obj = class1.nativeMayReturnNull(); + obj.toString(); + } + + void followMethodDeclarationOnlyBad(SkipImplementationClass1 obj1) { + Object obj2 = obj1.annotatedNullable(); + obj2.toString(); + } + + void followMethodDeclarationOnlyOk(SkipImplementationClass1 obj1) { + Object obj2 = obj1.notAnnotatedNullable(); + obj2.toString(); + } + + void dereferenceLocalNullableFieldBad() { + field.toString(); + } + + void dereferenceInterTargetField1Bad(Class1 class1) { + class1.field1.toString(); + } + + int dereferenceInterTargetField2Bad(Class1 class1) { + return class1.field2.x; + } + + void dereferenceUnannotatedMethodReturningNullBad(Class1 class1) { + class1.unannotatedReturnNull().toString(); + } + + static class Sub extends Class1.Sub { + @Override + public @Nullable Object subtypingInconsistency(Object object) { + return null; + } + } +} diff --git a/infer/tests/build_systems/buck_cross_module/.buckconfig b/infer/tests/build_systems/buck_cross_module/.buckconfig new file mode 100644 index 000000000..250f76f47 --- /dev/null +++ b/infer/tests/build_systems/buck_cross_module/.buckconfig @@ -0,0 +1,9 @@ +[buildfile] + includes = //DEFS + +[project] + ignore = .git, .ml, .mli + +[java] + source_level = 8 + target_level = 8 \ No newline at end of file diff --git a/infer/tests/build_systems/buck_cross_module/.buckversion b/infer/tests/build_systems/buck_cross_module/.buckversion new file mode 120000 index 000000000..0a46cf46a --- /dev/null +++ b/infer/tests/build_systems/buck_cross_module/.buckversion @@ -0,0 +1 @@ +../../../../.buckversion \ No newline at end of file diff --git a/infer/tests/build_systems/buck_cross_module/DEFS b/infer/tests/build_systems/buck_cross_module/DEFS new file mode 100644 index 000000000..bebab3220 --- /dev/null +++ b/infer/tests/build_systems/buck_cross_module/DEFS @@ -0,0 +1,52 @@ +import os + +original_java_library = java_library +def java_library( + name, + srcs=[], + **kwargs + ): + + original_java_library( + name=name, + srcs=srcs, + **kwargs + ) + + create_infer_genrule(name, srcs) + +original_android_library = android_library +def android_library( + name, + srcs=[], + **kwargs + ): + + original_android_library( + name=name, + srcs=srcs, + **kwargs + ) + + create_infer_genrule(name, srcs) + +def create_infer_genrule( + name, + srcs + ): + genrule_name = name + '_infer' + genrule( + name = genrule_name, + srcs=srcs, + cmd = ' '.join([ + os.getenv('INFER_BIN', 'infer'), + '--genrule-mode', + '--project-root', os.getenv('PROJECT_ROOT', os.environ['PWD']), + '--eradicate-only', + '--results-dir', '$OUT', + '--classpath', '$(classpath :{})'.format(name), + '--sourcepath', '$SRCDIR', + '--generated-classes', '$(location :{})'.format(name), + ]), + out = 'infer_out', + ) diff --git a/infer/tests/build_systems/buck_cross_module/Makefile b/infer/tests/build_systems/buck_cross_module/Makefile index 6c7fb2cda..f2c271e8c 100644 --- a/infer/tests/build_systems/buck_cross_module/Makefile +++ b/infer/tests/build_systems/buck_cross_module/Makefile @@ -4,24 +4,17 @@ # LICENSE file in the root directory of this source tree. TESTS_DIR = ../.. -ROOT_DIR = $(TESTS_DIR)/../.. -BUCK_TARGET = //infer/tests/build_systems/buck_cross_module/module2:module2 -INFERPRINT_OPTIONS = --project-root $(ROOT_DIR) --issues-tests -CLEAN_EXTRA = $(ROOT_DIR)/buck-out +BUCK_TARGET = //module2:module2 +INFERPRINT_OPTIONS = --issues-tests +CLEAN_EXTRA = buck-out +SOURCES = $(shell find . -name '*.java') include $(TESTS_DIR)/java.make include $(TESTS_DIR)/infer.make -$(OBJECTS): $(JAVA_SOURCE_FILES) - $(QUIET)cd $(ROOT_DIR) && \ - $(call silent_on_success,Compiling Buck cross module test tests,\ - INFER_BIN=$(INFER_BIN) \ - $(BUCK) build --no-cache $(BUCK_TARGET)) - infer-out/report.json: $(JAVA_DEPS) $(JAVA_SOURCE_FILES) - $(QUIET)cd $(ROOT_DIR) && \ - $(REMOVE_DIR) buck-out && \ + $(QUIET)$(REMOVE_DIR) buck-out && \ $(call silent_on_success,Testing Buck Java cross module integration,\ INFER_BIN=$(INFER_BIN) \ $(INFER_BIN) --results-dir $(CURDIR)/infer-out -- \ diff --git a/infer/tests/build_systems/buck_cross_module/annotations/BUCK b/infer/tests/build_systems/buck_cross_module/annotations/BUCK new file mode 100644 index 000000000..bc0b50a7f --- /dev/null +++ b/infer/tests/build_systems/buck_cross_module/annotations/BUCK @@ -0,0 +1,7 @@ +java_library( + name='annotations', + srcs=['Nullable.java'], + visibility=[ + 'PUBLIC' + ], +) diff --git a/infer/tests/build_systems/buck_cross_module/annotations/Nullable.java b/infer/tests/build_systems/buck_cross_module/annotations/Nullable.java new file mode 100644 index 000000000..429589abb --- /dev/null +++ b/infer/tests/build_systems/buck_cross_module/annotations/Nullable.java @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2018-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +package genrule.annotations; + +public @interface Nullable {} diff --git a/infer/tests/build_systems/buck_cross_module/issues.exp b/infer/tests/build_systems/buck_cross_module/issues.exp index 61d4601d5..de4d4ef00 100644 --- a/infer/tests/build_systems/buck_cross_module/issues.exp +++ b/infer/tests/build_systems/buck_cross_module/issues.exp @@ -1,2 +1,2 @@ -infer/tests/build_systems/buck_cross_module/module2/Class2.java, void Class2.crossModuleNPE1(), 1, NULL_DEREFERENCE, [start of procedure crossModuleNPE1(),start of procedure returnsNull(),return from a call to String Class1.returnsNull()] -infer/tests/build_systems/buck_cross_module/module2/Class2.java, void Class2.crossModuleNPE2(Class1), 1, NULL_DEREFERENCE, [start of procedure crossModuleNPE2(...)] +module2/Class2.java, crossmodule.module2.Class2.crossModuleNPE1():void, 1, NULL_DEREFERENCE, no_bucket, ERROR, [start of procedure crossModuleNPE1(),start of procedure returnsNull(),return from a call to String Class1.returnsNull()] +module2/Class2.java, crossmodule.module2.Class2.crossModuleNPE2(crossmodule.module1.Class1):void, 1, NULL_DEREFERENCE, no_bucket, ERROR, [start of procedure crossModuleNPE2(...)] diff --git a/infer/tests/build_systems/buck_cross_module/module1/BUCK b/infer/tests/build_systems/buck_cross_module/module1/BUCK index 7009d9de4..f828d55ef 100644 --- a/infer/tests/build_systems/buck_cross_module/module1/BUCK +++ b/infer/tests/build_systems/buck_cross_module/module1/BUCK @@ -2,7 +2,7 @@ java_library( name='module1', srcs=['Class1.java'], deps=[ - '//infer/tests/build_systems/genrule/annotations:annotations', + '//annotations:annotations', ], visibility=[ 'PUBLIC' diff --git a/infer/tests/build_systems/buck_cross_module/module2/BUCK b/infer/tests/build_systems/buck_cross_module/module2/BUCK index 44a247b05..783d8b20d 100644 --- a/infer/tests/build_systems/buck_cross_module/module2/BUCK +++ b/infer/tests/build_systems/buck_cross_module/module2/BUCK @@ -2,6 +2,6 @@ java_library( name='module2', srcs=['Class2.java'], deps=[ - '//infer/tests/build_systems/buck_cross_module/module1:module1' + '//module1:module1' ] ) diff --git a/infer/tests/build_systems/buck_javac_jar/Makefile b/infer/tests/build_systems/buck_javac_jar/Makefile index 2b37f4465..c03c21813 100644 --- a/infer/tests/build_systems/buck_javac_jar/Makefile +++ b/infer/tests/build_systems/buck_javac_jar/Makefile @@ -20,7 +20,7 @@ $(OBJECTS): $(SOURCES) $(BUCKCONFIG) $(TESTLOCK) $(BUCK) build --config tools.javac_jar= $(TARGET) infer-out/report.json: $(JAVA_DEPS) $(SOURCES) $(BUCKCONFIG) - $(TESTLOCK) $(REMOVE_DIR) buck-out && \ + $(QUIET)$(REMOVE_DIR) buck-out && \ $(call silent_on_success,Testing Buck Java integration with javac_jar,\ INFER_BIN=$(INFER_BIN) \ - $(TESTLOCK) $(INFER_BIN) $(INFER_OPTIONS) -- $(BUCK) build $(TARGET)) + $(INFER_BIN) $(INFER_OPTIONS) -- $(BUCK) build $(TARGET)) diff --git a/infer/tests/build_systems/genrule/.buckconfig b/infer/tests/build_systems/genrule/.buckconfig new file mode 100644 index 000000000..250f76f47 --- /dev/null +++ b/infer/tests/build_systems/genrule/.buckconfig @@ -0,0 +1,9 @@ +[buildfile] + includes = //DEFS + +[project] + ignore = .git, .ml, .mli + +[java] + source_level = 8 + target_level = 8 \ No newline at end of file diff --git a/infer/tests/build_systems/genrule/.buckversion b/infer/tests/build_systems/genrule/.buckversion new file mode 120000 index 000000000..0a46cf46a --- /dev/null +++ b/infer/tests/build_systems/genrule/.buckversion @@ -0,0 +1 @@ +../../../../.buckversion \ No newline at end of file diff --git a/infer/tests/build_systems/genrule/DEFS b/infer/tests/build_systems/genrule/DEFS new file mode 100644 index 000000000..bebab3220 --- /dev/null +++ b/infer/tests/build_systems/genrule/DEFS @@ -0,0 +1,52 @@ +import os + +original_java_library = java_library +def java_library( + name, + srcs=[], + **kwargs + ): + + original_java_library( + name=name, + srcs=srcs, + **kwargs + ) + + create_infer_genrule(name, srcs) + +original_android_library = android_library +def android_library( + name, + srcs=[], + **kwargs + ): + + original_android_library( + name=name, + srcs=srcs, + **kwargs + ) + + create_infer_genrule(name, srcs) + +def create_infer_genrule( + name, + srcs + ): + genrule_name = name + '_infer' + genrule( + name = genrule_name, + srcs=srcs, + cmd = ' '.join([ + os.getenv('INFER_BIN', 'infer'), + '--genrule-mode', + '--project-root', os.getenv('PROJECT_ROOT', os.environ['PWD']), + '--eradicate-only', + '--results-dir', '$OUT', + '--classpath', '$(classpath :{})'.format(name), + '--sourcepath', '$SRCDIR', + '--generated-classes', '$(location :{})'.format(name), + ]), + out = 'infer_out', + ) diff --git a/infer/tests/build_systems/genrule/Makefile b/infer/tests/build_systems/genrule/Makefile index 4a422df3b..c29b88101 100644 --- a/infer/tests/build_systems/genrule/Makefile +++ b/infer/tests/build_systems/genrule/Makefile @@ -4,41 +4,24 @@ # LICENSE file in the root directory of this source tree. TESTS_DIR = ../.. -ROOT_DIR = $(TESTS_DIR)/../.. -BUCK_TARGET = //infer/tests/build_systems/genrule/module2:module2 +BUCK_TARGET = //module2:module2 INFER_TARGET = $(BUCK_TARGET)_infer -SOURCES = $(wildcard $(TESTS_DIR)/codetoanalyze/java/infer/*.java) -OBJECTS = $(ROOT_DIR)/buck-out/genruletest/gen/infer/tests/build_systems/genrule/module2/lib__module2_compile__output/module2_compile.jar -JSON_REPORT = $(ROOT_DIR)/buck-out/gen/infer/tests/build_systems/genrule/module2/module2_infer/infer_out/report.json -INFERPRINT_OPTIONS = --project-root $(ROOT_DIR) --issues-tests - -# fake infer-out because we only copy the results.json from buck-out. -INFER_OUT = . +INFERPRINT_OPTIONS = --issues-tests +SOURCES = $(shell find . -name '*.java') +CLEAN_EXTRA = buck-out +INFER_OUT = buck-out/gen/module2/module2_infer/infer_out +JSON_REPORT = $(INFER_OUT)/report.json include $(TESTS_DIR)/java.make include $(TESTS_DIR)/infer.make -$(OBJECTS): $(JAVA_SOURCE_FILES) - $(QUIET)cd $(ROOT_DIR) && \ - $(call silent_on_success,Compiling Buck genrule for Java sources,\ - $(TESTLOCK) $(BUCK) build --no-cache $(BUCK_TARGET)) - -.PHONY: genrule -genrule: $(JSON_REPORT) - - -$(JSON_REPORT): $(JAVA_DEPS) $(JAVA_SOURCE_FILES) $(MAKEFILE_LIST) - $(QUIET)cd $(ROOT_DIR) && \ - $(TESTLOCK) $(REMOVE_DIR) buck-out && \ +$(JSON_REPORT): $(JAVA_DEPS) $(SOURCES) $(MAKEFILE_LIST) + $(QUIET)$(REMOVE_DIR) buck-out && \ $(call silent_on_success,Testing Buck genrule for Java integration,\ - INFER_BIN="$(INFER_BIN)" PROJECT_ROOT="$(PWD)" $(TESTLOCK) $(BUCK) build --no-cache $(INFER_TARGET)) + INFER_BIN="$(INFER_BIN)" $(BUCK) build --no-cache $(INFER_TARGET)) $(QUIET)touch $@ -report.json: $(JSON_REPORT) $(MAKEFILE_LIST) -# the report contains absolute paths - $(QUIET)sed -e 's#$(abspath $(TESTS_DIR))/##g' $< > $@ - -issues.exp.test$(TEST_SUFFIX): report.json $(INFER_BIN) +issues.exp.test$(TEST_SUFFIX): $(JSON_REPORT) $(INFER_BIN) $(QUIET)$(INFER_BIN) report -q \ - $(INFERPRINT_OPTIONS) $@ --from-json-report $< + $(INFERPRINT_OPTIONS) $@ --from-json-report $(JSON_REPORT) diff --git a/infer/tests/build_systems/genrule/issues.exp b/infer/tests/build_systems/genrule/issues.exp index d291f5511..ee3e5d866 100644 --- a/infer/tests/build_systems/genrule/issues.exp +++ b/infer/tests/build_systems/genrule/issues.exp @@ -1,10 +1,10 @@ -infer/tests/build_systems/genrule/module2/Class2.java, genrule.module2.Class2$Sub.subtypingInconsistency(java.lang.Object):java.lang.Object, 0, ERADICATE_INCONSISTENT_SUBCLASS_PARAMETER_ANNOTATION, no_bucket, WARNING, [First parameter `object` of method `Class2$Sub.subtypingInconsistency(...)` is not `@Nullable` but is declared `@Nullable`in the parent class method `Class1$Sub.subtypingInconsistency(...)`.] -infer/tests/build_systems/genrule/module2/Class2.java, genrule.module2.Class2$Sub.subtypingInconsistency(java.lang.Object):java.lang.Object, 0, ERADICATE_INCONSISTENT_SUBCLASS_RETURN_ANNOTATION, no_bucket, WARNING, [Method `Class2$Sub.subtypingInconsistency(...)` is annotated with `@Nullable` but overrides unannotated method `Class1$Sub.subtypingInconsistency(...)`.] -infer/tests/build_systems/genrule/module2/Class2.java, genrule.module2.Class2.dereferenceInterTargetField1Bad(genrule.module1.Class1):void, 1, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [The value of `class1.field1` in the call to `toString()` is nullable and is not locally checked for null. (Origin: field Class1.field1 at line 53)] -infer/tests/build_systems/genrule/module2/Class2.java, genrule.module2.Class2.dereferenceInterTargetField2Bad(genrule.module1.Class1):int, 1, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [Object `class1.field2` is nullable and is not locally checked for null when accessing field `Class1.x`. (Origin: field Class1.field2 at line 57)] -infer/tests/build_systems/genrule/module2/Class2.java, genrule.module2.Class2.dereferenceLocalNullableFieldBad():void, 1, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [The value of `Class2.field` in the call to `toString()` is nullable and is not locally checked for null. (Origin: field Class2.field at line 49)] -infer/tests/build_systems/genrule/module2/Class2.java, genrule.module2.Class2.followMethodDeclarationOnlyBad(genrule.module1.SkipImplementationClass1):void, 2, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [The value of `obj2` in the call to `toString()` is nullable and is not locally checked for null. (Origin: call to annotatedNullable() at line 39)] -infer/tests/build_systems/genrule/module2/Class2.java, genrule.module2.Class2.interTargetAbstractNPEBad(genrule.module1.Class1):void, 2, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [The value of `obj` in the call to `toString()` is nullable and is not locally checked for null. (Origin: call to abstractMayReturnNull() at line 29)] -infer/tests/build_systems/genrule/module2/Class2.java, genrule.module2.Class2.interTargetNPEBad():void, 2, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [The value of `obj` in the call to `toString()` is nullable and is not locally checked for null. (Origin: call to returnsNull() at line 24)] -infer/tests/build_systems/genrule/module2/Class2.java, genrule.module2.Class2.interTargetNativeNPEBad(genrule.module1.Class1):void, 2, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [The value of `obj` in the call to `toString()` is nullable and is not locally checked for null. (Origin: call to nativeMayReturnNull() at line 34)] -infer/tests/build_systems/genrule/module2/Class2.java, genrule.module2.Class2.localNPE2Bad():void, 2, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [The value of `obj` in the call to `toString()` is nullable and is not locally checked for null. (Origin: null constant at line 19)] +module2/Class2.java, genrule.module2.Class2$Sub.subtypingInconsistency(java.lang.Object):java.lang.Object, 0, ERADICATE_INCONSISTENT_SUBCLASS_PARAMETER_ANNOTATION, no_bucket, WARNING, [First parameter `object` of method `Class2$Sub.subtypingInconsistency(...)` is not `@Nullable` but is declared `@Nullable`in the parent class method `Class1$Sub.subtypingInconsistency(...)`.] +module2/Class2.java, genrule.module2.Class2$Sub.subtypingInconsistency(java.lang.Object):java.lang.Object, 0, ERADICATE_INCONSISTENT_SUBCLASS_RETURN_ANNOTATION, no_bucket, WARNING, [Method `Class2$Sub.subtypingInconsistency(...)` is annotated with `@Nullable` but overrides unannotated method `Class1$Sub.subtypingInconsistency(...)`.] +module2/Class2.java, genrule.module2.Class2.dereferenceInterTargetField1Bad(genrule.module1.Class1):void, 1, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [The value of `class1.field1` in the call to `toString()` is nullable and is not locally checked for null. (Origin: field Class1.field1 at line 53)] +module2/Class2.java, genrule.module2.Class2.dereferenceInterTargetField2Bad(genrule.module1.Class1):int, 1, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [Object `class1.field2` is nullable and is not locally checked for null when accessing field `Class1.x`. (Origin: field Class1.field2 at line 57)] +module2/Class2.java, genrule.module2.Class2.dereferenceLocalNullableFieldBad():void, 1, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [The value of `Class2.field` in the call to `toString()` is nullable and is not locally checked for null. (Origin: field Class2.field at line 49)] +module2/Class2.java, genrule.module2.Class2.followMethodDeclarationOnlyBad(genrule.module1.SkipImplementationClass1):void, 2, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [The value of `obj2` in the call to `toString()` is nullable and is not locally checked for null. (Origin: call to annotatedNullable() at line 39)] +module2/Class2.java, genrule.module2.Class2.interTargetAbstractNPEBad(genrule.module1.Class1):void, 2, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [The value of `obj` in the call to `toString()` is nullable and is not locally checked for null. (Origin: call to abstractMayReturnNull() at line 29)] +module2/Class2.java, genrule.module2.Class2.interTargetNPEBad():void, 2, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [The value of `obj` in the call to `toString()` is nullable and is not locally checked for null. (Origin: call to returnsNull() at line 24)] +module2/Class2.java, genrule.module2.Class2.interTargetNativeNPEBad(genrule.module1.Class1):void, 2, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [The value of `obj` in the call to `toString()` is nullable and is not locally checked for null. (Origin: call to nativeMayReturnNull() at line 34)] +module2/Class2.java, genrule.module2.Class2.localNPE2Bad():void, 2, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [The value of `obj` in the call to `toString()` is nullable and is not locally checked for null. (Origin: null constant at line 19)] diff --git a/infer/tests/build_systems/genrule/module1/BUCK b/infer/tests/build_systems/genrule/module1/BUCK index d39b12ca6..4ac82ec7d 100644 --- a/infer/tests/build_systems/genrule/module1/BUCK +++ b/infer/tests/build_systems/genrule/module1/BUCK @@ -2,7 +2,7 @@ java_library( name='module1', srcs=glob(["*.java"]), deps=[ - '//infer/tests/build_systems/genrule/annotations:annotations', + '//annotations:annotations', ], visibility=[ 'PUBLIC' diff --git a/infer/tests/build_systems/genrule/module2/BUCK b/infer/tests/build_systems/genrule/module2/BUCK index a1f50d968..33f3d881f 100644 --- a/infer/tests/build_systems/genrule/module2/BUCK +++ b/infer/tests/build_systems/genrule/module2/BUCK @@ -2,7 +2,7 @@ java_library( name='module2', srcs=glob(["*.java"]), deps=[ - '//infer/tests/build_systems/genrule/module1:module1', - '//infer/tests/build_systems/genrule/annotations:annotations', + '//module1:module1', + '//annotations:annotations', ] )