[nullsafe] Consolidate and expand tests for known initializers

Summary:
1. Let's move it to the file dedicated to this particular warning.
2. Make it more general (Activity was just a particular case) and describe in comments what it really does.

Reviewed By: ngorogiannis

Differential Revision: D17205919

fbshipit-source-id: 82bf5e9bd
master
Mitya Lyubarskiy 5 years ago committed by Facebook Github Bot
parent 260176251c
commit 5bd61e75f2

@ -1,21 +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.
*/
package codetoanalyze.java.nullsafe_default;
import android.app.Activity;
import android.os.Bundle;
public class ActivityFieldNotInitialized {
class BadActivityWithOnCreate extends Activity {
private String field;
protected void onCreate(Bundle bundle) {}
}
}

@ -7,6 +7,8 @@
package codetoanalyze.java.nullsafe_default; package codetoanalyze.java.nullsafe_default;
import android.app.Activity;
import android.os.Bundle;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.widget.EditText; import android.widget.EditText;
import com.facebook.infer.annotation.Assertions; import com.facebook.infer.annotation.Assertions;
@ -163,6 +165,52 @@ public class FieldNotInitialized {
} }
} }
/**
* There is a predefined list of classes which have known methods that act like initializers. If a
* class extends such special class and initializes a field in such whitelisted method, we don't
* require initializing this field in constructor. (NOTE: To do the same in non whitelisted class
* one can use @Initializer annotation instead).
*/
class TestKnownInitializers {
// nullsafe knows that Activity.onCreate is a special initilizer.
class KnownInitializers extends Activity {
String initInConstructorIsOK;
String initInSpecialMethodIsOK;
String initInUnknownMethodIsBAD;
KnownInitializers() {
initInConstructorIsOK = "";
}
// onCreate is a special method
protected void onCreate(Bundle bundle) {
initInSpecialMethodIsOK = "";
}
protected void someOtherMethod(Bundle bundle) {
// BAD: This method is unknown (and does not have @Initializer annotation either).
initInUnknownMethodIsBAD = "";
}
}
abstract class FakeActivity {
abstract void onCreate(Bundle bundle);
}
class SimplyOnCreateWontDoATrick extends FakeActivity {
String initInUnknownMethodIsBAD;
// Though we use onCreate method, the class does not extend one of the known
// classes that are known to have such a property, so it does not count.
protected void onCreate(Bundle bundle) {
// BAD: This method is unknown (and does not have @Initializer annotation either).
initInUnknownMethodIsBAD = "";
}
}
}
/** /**
* If a method is marked with @Initializer annotation, we essentially treat is as a constuctror: if * If a method is marked with @Initializer annotation, we essentially treat is as a constuctror: if
* a field is initialized in one of such methods, we assume this method will be called before using * a field is initialized in one of such methods, we assume this method will be called before using

@ -7,8 +7,6 @@
package codetoanalyze.java.nullsafe_default; package codetoanalyze.java.nullsafe_default;
import android.app.Activity;
import android.os.Bundle;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import com.facebook.infer.annotation.Cleanup; import com.facebook.infer.annotation.Cleanup;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -82,18 +80,3 @@ public class FieldNotNullable {
} }
} }
class MixedInitializers extends Activity {
private String field1 = "1";
private String field2;
private String field3;
MixedInitializers() {
field2 = "2";
}
protected void onCreate(Bundle bundle) {
field3 = "3";
}
}

@ -1,4 +1,3 @@
codetoanalyze/java/nullsafe-default/ActivityFieldNotInitialized.java, codetoanalyze.java.nullsafe_default.ActivityFieldNotInitialized$BadActivityWithOnCreate.<init>(codetoanalyze.java.nullsafe_default.ActivityFieldNotInitialized), 0, ERADICATE_FIELD_NOT_INITIALIZED, no_bucket, WARNING, [Field `ActivityFieldNotInitialized$BadActivityWithOnCreate.field` is not initialized in the constructor and is not declared `@Nullable`]
codetoanalyze/java/nullsafe-default/ButterKnife.java, codetoanalyze.java.nullsafe_default.ButterKnife$TestNotInitialized.<init>(codetoanalyze.java.nullsafe_default.ButterKnife), 0, ERADICATE_FIELD_NOT_INITIALIZED, no_bucket, WARNING, [Field `ButterKnife$TestNotInitialized.notInitializedNormalIsBAD` is not initialized in the constructor and is not declared `@Nullable`] codetoanalyze/java/nullsafe-default/ButterKnife.java, codetoanalyze.java.nullsafe_default.ButterKnife$TestNotInitialized.<init>(codetoanalyze.java.nullsafe_default.ButterKnife), 0, ERADICATE_FIELD_NOT_INITIALIZED, no_bucket, WARNING, [Field `ButterKnife$TestNotInitialized.notInitializedNormalIsBAD` is not initialized in the constructor and is not declared `@Nullable`]
codetoanalyze/java/nullsafe-default/ButterKnife.java, codetoanalyze.java.nullsafe_default.ButterKnife.assignNullToNormalIsBAD():void, 1, ERADICATE_FIELD_NOT_NULLABLE, no_bucket, WARNING, [Field `ButterKnife.normal` can be null but is not declared `@Nullable`. (Origin: null constant at line 76)] codetoanalyze/java/nullsafe-default/ButterKnife.java, codetoanalyze.java.nullsafe_default.ButterKnife.assignNullToNormalIsBAD():void, 1, ERADICATE_FIELD_NOT_NULLABLE, no_bucket, WARNING, [Field `ButterKnife.normal` can be null but is not declared `@Nullable`. (Origin: null constant at line 76)]
codetoanalyze/java/nullsafe-default/ButterKnife.java, codetoanalyze.java.nullsafe_default.ButterKnife.convertingToNotNullableForNullableIsBAD():java.lang.String, 0, ERADICATE_RETURN_NOT_NULLABLE, no_bucket, WARNING, [Method `convertingToNotNullableForNullableIsBAD()` may return null but it is not annotated with `@Nullable`. (Origin: field ButterKnife.nullable at line 47)] codetoanalyze/java/nullsafe-default/ButterKnife.java, codetoanalyze.java.nullsafe_default.ButterKnife.convertingToNotNullableForNullableIsBAD():java.lang.String, 0, ERADICATE_RETURN_NOT_NULLABLE, no_bucket, WARNING, [Method `convertingToNotNullableForNullableIsBAD()` may return null but it is not annotated with `@Nullable`. (Origin: field ButterKnife.nullable at line 47)]
@ -27,12 +26,14 @@ codetoanalyze/java/nullsafe-default/FieldNotInitialized.java, codetoanalyze.java
codetoanalyze/java/nullsafe-default/FieldNotInitialized.java, codetoanalyze.java.nullsafe_default.TestInitializerAnnotation.build():java.lang.Object, 5, ERADICATE_CONDITION_REDUNDANT, no_bucket, WARNING, [The condition TestInitializerAnnotation.initInInitilizerMethod2IsOK is always true according to the existing annotations.] codetoanalyze/java/nullsafe-default/FieldNotInitialized.java, codetoanalyze.java.nullsafe_default.TestInitializerAnnotation.build():java.lang.Object, 5, ERADICATE_CONDITION_REDUNDANT, no_bucket, WARNING, [The condition TestInitializerAnnotation.initInInitilizerMethod2IsOK is always true according to the existing annotations.]
codetoanalyze/java/nullsafe-default/FieldNotInitialized.java, codetoanalyze.java.nullsafe_default.TestInitializerAnnotation.build():java.lang.Object, 5, ERADICATE_CONDITION_REDUNDANT, no_bucket, WARNING, [The condition TestInitializerAnnotation.initInInitilizerMethod1IsOK is always true according to the existing annotations.] codetoanalyze/java/nullsafe-default/FieldNotInitialized.java, codetoanalyze.java.nullsafe_default.TestInitializerAnnotation.build():java.lang.Object, 5, ERADICATE_CONDITION_REDUNDANT, no_bucket, WARNING, [The condition TestInitializerAnnotation.initInInitilizerMethod1IsOK is always true according to the existing annotations.]
codetoanalyze/java/nullsafe-default/FieldNotInitialized.java, codetoanalyze.java.nullsafe_default.TestInitializerAnnotation.set4(java.lang.String):void, 2, ERADICATE_FIELD_NOT_NULLABLE, no_bucket, WARNING, [Field `TestInitializerAnnotation.initByNullableInInitializedMethodIsBAD` can be null but is not declared `@Nullable`. (Origin: method parameter value)] codetoanalyze/java/nullsafe-default/FieldNotInitialized.java, codetoanalyze.java.nullsafe_default.TestInitializerAnnotation.set4(java.lang.String):void, 2, ERADICATE_FIELD_NOT_NULLABLE, no_bucket, WARNING, [Field `TestInitializerAnnotation.initByNullableInInitializedMethodIsBAD` can be null but is not declared `@Nullable`. (Origin: method parameter value)]
codetoanalyze/java/nullsafe-default/FieldNotNullable.java, codetoanalyze.java.nullsafe_default.CanAssignNullInCleanupMethods.assignNullInAnyOtherMethodIsBAD():void, 1, ERADICATE_FIELD_NOT_NULLABLE, no_bucket, WARNING, [Field `CanAssignNullInCleanupMethods.someObject` can be null but is not declared `@Nullable`. (Origin: null constant at line 46)] codetoanalyze/java/nullsafe-default/FieldNotInitialized.java, codetoanalyze.java.nullsafe_default.TestKnownInitializers$KnownInitializers.<init>(codetoanalyze.java.nullsafe_default.TestKnownInitializers), 0, ERADICATE_FIELD_NOT_INITIALIZED, no_bucket, WARNING, [Field `TestKnownInitializers$KnownInitializers.initInUnknownMethodIsBAD` is not initialized in the constructor and is not declared `@Nullable`]
codetoanalyze/java/nullsafe-default/FieldNotNullable.java, codetoanalyze.java.nullsafe_default.FieldNotNullable.<init>(), 4, ERADICATE_FIELD_NOT_NULLABLE, no_bucket, WARNING, [Field `FieldNotNullable.initializeNonNullableWithNullIsBAD` can be null but is not declared `@Nullable`. (Origin: null constant at line 54)] codetoanalyze/java/nullsafe-default/FieldNotInitialized.java, codetoanalyze.java.nullsafe_default.TestKnownInitializers$SimplyOnCreateWontDoATrick.<init>(codetoanalyze.java.nullsafe_default.TestKnownInitializers), 0, ERADICATE_FIELD_NOT_INITIALIZED, no_bucket, WARNING, [Field `TestKnownInitializers$SimplyOnCreateWontDoATrick.initInUnknownMethodIsBAD` is not initialized in the constructor and is not declared `@Nullable`]
codetoanalyze/java/nullsafe-default/FieldNotNullable.java, codetoanalyze.java.nullsafe_default.CanAssignNullInCleanupMethods.assignNullInAnyOtherMethodIsBAD():void, 1, ERADICATE_FIELD_NOT_NULLABLE, no_bucket, WARNING, [Field `CanAssignNullInCleanupMethods.someObject` can be null but is not declared `@Nullable`. (Origin: null constant at line 44)]
codetoanalyze/java/nullsafe-default/FieldNotNullable.java, codetoanalyze.java.nullsafe_default.FieldNotNullable.<init>(), 4, ERADICATE_FIELD_NOT_NULLABLE, no_bucket, WARNING, [Field `FieldNotNullable.initializeNonNullableWithNullIsBAD` can be null but is not declared `@Nullable`. (Origin: null constant at line 52)]
codetoanalyze/java/nullsafe-default/FieldNotNullable.java, codetoanalyze.java.nullsafe_default.FieldNotNullable.getNullable():java.lang.String, 0, ERADICATE_RETURN_OVER_ANNOTATED, no_bucket, WARNING, [Method `getNullable()` is annotated with `@Nullable` but never returns null.] codetoanalyze/java/nullsafe-default/FieldNotNullable.java, codetoanalyze.java.nullsafe_default.FieldNotNullable.getNullable():java.lang.String, 0, ERADICATE_RETURN_OVER_ANNOTATED, no_bucket, WARNING, [Method `getNullable()` is annotated with `@Nullable` but never returns null.]
codetoanalyze/java/nullsafe-default/FieldNotNullable.java, codetoanalyze.java.nullsafe_default.FieldNotNullable.setNullableToNotNullableIsBAD(java.lang.String):void, 1, ERADICATE_FIELD_NOT_NULLABLE, no_bucket, WARNING, [Field `FieldNotNullable.notNullable` can be null but is not declared `@Nullable`. (Origin: null constant at line 67)] codetoanalyze/java/nullsafe-default/FieldNotNullable.java, codetoanalyze.java.nullsafe_default.FieldNotNullable.setNullableToNotNullableIsBAD(java.lang.String):void, 1, ERADICATE_FIELD_NOT_NULLABLE, no_bucket, WARNING, [Field `FieldNotNullable.notNullable` can be null but is not declared `@Nullable`. (Origin: null constant at line 65)]
codetoanalyze/java/nullsafe-default/FieldNotNullable.java, codetoanalyze.java.nullsafe_default.FieldNotNullable.setNullableToNotNullableIsBAD(java.lang.String):void, 2, ERADICATE_FIELD_NOT_NULLABLE, no_bucket, WARNING, [Field `FieldNotNullable.notNullable` can be null but is not declared `@Nullable`. (Origin: method parameter s)] codetoanalyze/java/nullsafe-default/FieldNotNullable.java, codetoanalyze.java.nullsafe_default.FieldNotNullable.setNullableToNotNullableIsBAD(java.lang.String):void, 2, ERADICATE_FIELD_NOT_NULLABLE, no_bucket, WARNING, [Field `FieldNotNullable.notNullable` can be null but is not declared `@Nullable`. (Origin: method parameter s)]
codetoanalyze/java/nullsafe-default/FieldNotNullable.java, codetoanalyze.java.nullsafe_default.FieldNotNullable.setNullableToNotNullableIsBAD(java.lang.String):void, 3, ERADICATE_FIELD_NOT_NULLABLE, no_bucket, WARNING, [Field `FieldNotNullable.notNullable` can be null but is not declared `@Nullable`. (Origin: call to getNullable() at line 69)] codetoanalyze/java/nullsafe-default/FieldNotNullable.java, codetoanalyze.java.nullsafe_default.FieldNotNullable.setNullableToNotNullableIsBAD(java.lang.String):void, 3, ERADICATE_FIELD_NOT_NULLABLE, no_bucket, WARNING, [Field `FieldNotNullable.notNullable` can be null but is not declared `@Nullable`. (Origin: call to getNullable() at line 67)]
codetoanalyze/java/nullsafe-default/InconsistentSubclassAnnotation.java, codetoanalyze.java.nullsafe_default.ExtendsExternalLibrary.externalMethod2(java.lang.Object):void, 0, ERADICATE_INCONSISTENT_SUBCLASS_PARAMETER_ANNOTATION, no_bucket, WARNING, [First parameter `object` of method `ExtendsExternalLibrary.externalMethod2(...)` is not `@Nullable` but is declared `@Nullable`in the parent class method `SomeExternalClass.externalMethod2(...)`.] codetoanalyze/java/nullsafe-default/InconsistentSubclassAnnotation.java, codetoanalyze.java.nullsafe_default.ExtendsExternalLibrary.externalMethod2(java.lang.Object):void, 0, ERADICATE_INCONSISTENT_SUBCLASS_PARAMETER_ANNOTATION, no_bucket, WARNING, [First parameter `object` of method `ExtendsExternalLibrary.externalMethod2(...)` is not `@Nullable` but is declared `@Nullable`in the parent class method `SomeExternalClass.externalMethod2(...)`.]
codetoanalyze/java/nullsafe-default/InconsistentSubclassAnnotation.java, codetoanalyze.java.nullsafe_default.InconsistentSubclassAnnotation.implementInAnotherFile(java.lang.String):java.lang.String, 0, ERADICATE_INCONSISTENT_SUBCLASS_PARAMETER_ANNOTATION, no_bucket, WARNING, [First parameter `s` of method `InconsistentSubclassAnnotation.implementInAnotherFile(...)` is not `@Nullable` but is declared `@Nullable`in the parent class method `InconsistentSubclassAnnotationInterface.implementInAnotherFile(...)`.] codetoanalyze/java/nullsafe-default/InconsistentSubclassAnnotation.java, codetoanalyze.java.nullsafe_default.InconsistentSubclassAnnotation.implementInAnotherFile(java.lang.String):java.lang.String, 0, ERADICATE_INCONSISTENT_SUBCLASS_PARAMETER_ANNOTATION, no_bucket, WARNING, [First parameter `s` of method `InconsistentSubclassAnnotation.implementInAnotherFile(...)` is not `@Nullable` but is declared `@Nullable`in the parent class method `InconsistentSubclassAnnotationInterface.implementInAnotherFile(...)`.]
codetoanalyze/java/nullsafe-default/InconsistentSubclassAnnotation.java, codetoanalyze.java.nullsafe_default.InconsistentSubclassAnnotation.overloadedMethod():java.lang.Object, 0, ERADICATE_INCONSISTENT_SUBCLASS_RETURN_ANNOTATION, no_bucket, WARNING, [Method `InconsistentSubclassAnnotation.overloadedMethod()` is annotated with `@Nullable` but overrides unannotated method `InconsistentSubclassAnnotationInterface.overloadedMethod()`.] codetoanalyze/java/nullsafe-default/InconsistentSubclassAnnotation.java, codetoanalyze.java.nullsafe_default.InconsistentSubclassAnnotation.overloadedMethod():java.lang.Object, 0, ERADICATE_INCONSISTENT_SUBCLASS_RETURN_ANNOTATION, no_bucket, WARNING, [Method `InconsistentSubclassAnnotation.overloadedMethod()` is annotated with `@Nullable` but overrides unannotated method `InconsistentSubclassAnnotationInterface.overloadedMethod()`.]

Loading…
Cancel
Save