You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

368 lines
7.3 KiB

/*
* 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.eradicate;
import android.app.Activity;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.View;
import com.facebook.infer.annotation.Assertions;
import com.facebook.infer.annotation.Cleanup;
import com.facebook.infer.annotation.Initializer;
import javax.annotation.Nullable;
abstract class A {
final String fld;
A(String s) {
this.fld = s;
}
}
// for butterknife
@interface InjectView {}
class FragmentExample extends Fragment {
View view;
@Override
public void onDestroyView() {
view = null;
}
}
public class FieldNotNullable extends A {
@Nullable String x;
String y;
String fld; // Shadow the field defined in A
String static_s = null; // Static initializer error
FieldNotNullable(String s) {
super(s);
x = null;
y = s;
this.fld = s;
}
void setXNull() {
x = null;
}
void setXNullable(@Nullable String s) {
x = s;
}
void setYNull() {
y = null;
}
void setYNullable(@Nullable String s) {
y = s;
}
FieldNotNullable(Integer n) {
super("");
this.fld = "";
y = x == null ? "abc" : "def";
}
}
class MixedInitializers extends Activity {
private String field1 = "1";
private String field2;
private String field3;
MixedInitializers() {
field2 = "2";
}
protected void onCreate(Bundle bundle) {
field3 = "3";
}
}
class TestInitializerBuilder {
String required1;
String required2;
@Nullable String optional;
// No FIELD_NOT_INITIALIZED error should be reported, because of the @Initializer annotations.
TestInitializerBuilder() {}
// This is an initializer and must always be called before build().
@Initializer
TestInitializerBuilder setRequired1(String required1) {
this.required1 = required1;
return this;
}
// This is an initializer and must always be called before build().
@Initializer
TestInitializerBuilder setRequired2(String required2) {
this.required2 = required2;
return this;
}
TestInitializerBuilder setOptional(String optional) {
this.optional = optional;
return this;
}
TestInitializer build() {
// Fail hard if the required fields are not initialzed
Assertions.assertCondition(required1 != null && required2 != null);
return new TestInitializer(this);
}
@Cleanup
void testCleanup() {
this.required1 = null;
this.required2 = null;
this.optional = null;
}
}
class TestInitializer {
String required1; // should always be set
String required2; // should always be set
@Nullable String optional; // optionally set
TestInitializer(TestInitializerBuilder b) {
required1 = b.required1;
required2 = b.required2;
optional = b.optional;
}
static void testInitializerClientA() {
TestInitializerBuilder b = new TestInitializerBuilder();
b.setRequired1("hello");
b.setRequired2("world");
TestInitializer x = b.build();
}
static void testInitializerClientB() {
TestInitializerBuilder b = new TestInitializerBuilder();
b.setRequired1("a");
b.setRequired2("b");
b.setOptional("c");
TestInitializer x = b.build();
}
}
class NestedFieldAccess {
class C {
@Nullable String s;
}
class CC {
@Nullable C c;
}
class CCC {
@Nullable CC cc;
}
public class Test {
@Nullable String s;
C myc;
Test() {
myc = new C();
}
void test() {
if (s != null) {
int n = s.length();
}
}
void test1() {
if (myc.s != null) {
int n = myc.s.length();
}
}
void test2(C c) {
if (c.s != null) {
int n = c.s.length();
}
}
void test2_local() {
C c = new C();
if (c.s != null) {
int n = c.s.length();
}
}
void test3(CC cc) {
if (cc.c != null && cc.c.s != null) {
int n = cc.c.s.length();
}
}
void test4(CCC ccc) {
if (ccc.cc != null && ccc.cc.c != null && ccc.cc.c.s != null) {
int n = ccc.cc.c.s.length();
}
}
void test5(@Nullable CCC ccc) {
if (ccc == null || ccc.cc == null || ccc.cc.c == null || ccc.cc.c.s == null) {
} else {
int n = ccc.cc.c.s.length();
}
}
}
class TestFunctionsIdempotent {
@Nullable String s;
String dontAssignNull;
TestFunctionsIdempotent() {
dontAssignNull = "";
}
@Nullable
String getS(int n) {
return s;
}
TestFunctionsIdempotent getSelf() {
return this;
}
void FlatOK1(TestFunctionsIdempotent x) {
if (getS(3) != null) {
dontAssignNull = getS(3);
}
}
void FlatOK2(TestFunctionsIdempotent x) {
if (x.getS(3) != null) {
dontAssignNull = x.getS(3);
}
}
void FlatBAD1(TestFunctionsIdempotent x) {
if (x.getS(3) != null) {
dontAssignNull = getS(3);
}
}
void FlatBAD2(TestFunctionsIdempotent x) {
if (x.getS(3) != null) {
dontAssignNull = x.getS(4);
}
}
void NestedOK1() {
if (getSelf().getS(3) != null) {
dontAssignNull = getSelf().getS(3);
}
}
void NestedOK2() {
if (getSelf().getSelf().getS(3) != null) {
dontAssignNull = getSelf().getSelf().getS(3);
}
}
void NestedBAD1() {
if (getSelf().getS(3) != null) {
dontAssignNull = getSelf().getS(4);
}
}
void NestedBAD2() {
if (getS(3) != null) {
dontAssignNull = getSelf().getS(3);
}
}
void NestedBAD3() {
if (getSelf().getSelf().getS(3) != null) {
dontAssignNull = getSelf().getS(3);
}
}
}
class TestContainsKey {
void testMapContainsKey(java.util.Map<Integer, String> m) {
if (m.containsKey(3)) {
m.get(3).isEmpty();
}
}
void testMapContainsKeyInsideWhileLoop(java.util.Map<Integer, String> m) {
while (true) {
if (m.containsKey(3)) {
m.get(3).isEmpty();
}
}
}
void testImmutableMapContainsKey(com.google.common.collect.ImmutableMap<Integer, String> m) {
if (m.containsKey(3)) {
m.get(3).isEmpty();
}
}
}
// Test Map.put()
class TestPut {
String dontAssignNull = "";
public void putConstString(java.util.Map<String, String> map, String key) {
map.put(key, "abc");
dontAssignNull = map.get(key);
}
public void putNull(java.util.Map<String, String> map, String key) {
map.put(key, "abc");
map.put(key, null);
dontAssignNull = map.get(key);
}
public void putWithContainsKey(java.util.Map<String, String> map, String key) {
if (!map.containsKey(key)) {
map.put(key, "abc");
}
dontAssignNull = map.get(key);
}
}
// support assignments of null to @InjectView fields, generated by butterknife
class SupportButterKnife {
@InjectView String s;
SupportButterKnife() {}
void dereferencingIsOK() {
int n = s.length();
}
void assignNullIsOK() {
s = null;
}
}
void methodWithNullableCapturedParameterBad_FN(@Nullable Object parameter) {
Object object =
new Object() {
void foo() {
parameter.toString();
}
};
}
}