|
|
|
/*
|
|
|
|
* Copyright (c) 2017 - 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.checkers;
|
|
|
|
import javax.annotation.Nullable;
|
|
|
|
|
|
|
|
public class NullableSuggest {
|
|
|
|
private Object obj0;
|
|
|
|
@Nullable private Object obj1;
|
|
|
|
|
|
|
|
private static class OtherClass {
|
|
|
|
private Object obj2;
|
|
|
|
@Nullable private Object obj3;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void noAssignNullOk() {
|
|
|
|
}
|
|
|
|
|
|
|
|
public void assignNotNullOk() {
|
|
|
|
obj0 = new Object();
|
|
|
|
obj1 = new Object();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void assignNullBad() {
|
|
|
|
obj0 = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void assignNullToNullableOk() {
|
|
|
|
obj1 = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void assignNullToFieldInOtherClassBad() {
|
|
|
|
OtherClass oc = new OtherClass();
|
|
|
|
oc.obj2 = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void assignNullToNullableFieldInOtherClassOk() {
|
|
|
|
OtherClass oc = new OtherClass();
|
|
|
|
oc.obj3 = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void assignNullToNullableFieldTransitiveOk(boolean flag) {
|
|
|
|
Object origin = null;
|
|
|
|
Object intermediate = flag ? origin : new Object();
|
|
|
|
obj1 = intermediate;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void assignNullToFieldTransitiveBad(boolean flag) {
|
|
|
|
Object origin = null;
|
|
|
|
Object intermediate = flag ? origin : new Object();
|
|
|
|
obj0 = intermediate;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void assignNullToNullableFieldTransitiveLoopOk(int n) {
|
|
|
|
Object origin = null;
|
|
|
|
Object arr[] = new Object[n];
|
|
|
|
for (int i = 0; i < n; ++i) {
|
|
|
|
arr[i] = origin;
|
|
|
|
}
|
|
|
|
if (n > 0) {
|
|
|
|
obj1 = arr[0];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void assignNullToFieldTransitiveLoopBad(int n) {
|
|
|
|
Object origin = null;
|
|
|
|
Object arr[] = new Object[n];
|
|
|
|
for (int i = 0; i < n; ++i) {
|
|
|
|
arr[i] = origin;
|
|
|
|
}
|
|
|
|
if (n > 0) {
|
|
|
|
obj0 = arr[0];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void multipleChainsAlwaysSelectShortestBad(boolean flag) {
|
|
|
|
Object o0 = null;
|
|
|
|
Object o1 = null;
|
|
|
|
if (flag) {
|
|
|
|
o1 = o0;
|
|
|
|
}
|
|
|
|
obj0 = o1;
|
|
|
|
// The analysis should report error trace o1->obj0, rather than o0->o1->obj0
|
|
|
|
}
|
|
|
|
|
|
|
|
public void compareNullToFieldBad() {
|
|
|
|
OtherClass oc = new OtherClass();
|
|
|
|
if (obj0 == null) {
|
|
|
|
// Pretend that we did something here...
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// The analysis should not suggest @Nullable on OtherClass.obj2 here
|
|
|
|
oc.obj2 = obj0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void compareNullToNullableFieldOk() {
|
|
|
|
if (obj1 == null) {
|
|
|
|
// Pretend that we did something here...
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|