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.

209 lines
4.7 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.nullsafe;
import external.library.SomeExternalClass;
import javax.annotation.Nullable;
interface VariousMethods {
String valBoth(String arg);
@Nullable
String nullableReturn(String arg);
String nullableArg(@Nullable String arg);
@Nullable
String nullableBoth(@Nullable String arg);
}
interface Overloads {
String overload(int arg);
String overload(@Nullable String arg);
String overload(String arg1, int arg2);
String overload(String arg1, String arg2);
void notOverload(@Nullable Object arg);
}
// Check return annotations
abstract class ReturnValToNullBAD implements VariousMethods {
@Nullable
public String valBoth(String arg) {
return null;
}
}
abstract class ReturnNullToValOK implements VariousMethods {
public abstract String nullableReturn(String arg);
}
abstract class ReturnValFromValAndNullFromNullOK implements VariousMethods {
@Nullable
public String nullableReturn(String arg) {
return null;
}
public String valBoth(String arg) {
return arg;
}
}
abstract class AbstractReturnValToNullFN implements VariousMethods {
// An abstract override method with inconsistent signature is not reported
@Nullable
public abstract String valBoth(String arg);
}
// Check parameter annotations
abstract class ArgValToNullOK implements VariousMethods {
public String valBoth(@Nullable String arg) {
return "OK";
}
}
abstract class ArgNullToValBAD implements VariousMethods {
public String nullableArg(String arg) {
return arg;
}
}
abstract class ArgNullToValForInterfaceInAnotherFileBAD
implements InconsistentSubclassAnnotationInterface {
public String implementInAnotherFile(String s) {
return "BAD";
}
}
abstract class ArgValToValAndNullToNullOK implements VariousMethods {
public String valBoth(String arg) {
return arg;
}
@Nullable
public String nullableBoth(@Nullable String arg) {
return arg;
}
}
// Check overrides + overloads
// These are 'good' cases with real overrides
abstract class OverrideExistingCorrectlyOK implements Overloads {
public String overload(int arg) {
return "OK";
}
public String overload(@Nullable String arg) {
return "OK";
}
public String overload(String arg1, int arg2) {
return arg1;
}
public String overload(String arg1, String arg2) {
return arg1;
}
}
abstract class NoOverrideSinceDifferentTypesOK implements Overloads {
@Nullable
public String overload(Object arg) {
return null;
}
public String overload(Double arg) {
return arg.toString();
}
// Although, String is a subtype of Object, this method is not an override
public void notOverload(String arg) {
return;
}
}
// This is just a smoke test to check that incorrect overrides of overloaded methods get reported
abstract class OverloadExistingIncorrectBAD implements Overloads {
@Nullable
public String overload(String arg1, String arg2) {
return null;
}
}
// Check constructors
class ConstructorsAreExcluded {
class Base {
Base(@Nullable String s) {}
}
class Derived extends Base {
Derived(String s) { // OK: there's no sub-typing between constructors
super(s);
}
}
}
// Check interop with external libraries
class ExtendsExternalLibrary extends SomeExternalClass {
@Override
public @Nullable Object externalMethod1() {
// subtyping error on the return type not reported as we cannot
// rely on the external libraries to be correctly annotated
return null;
}
@Override
public void externalMethod2(Object object) {
// subtyping error on the parameter type are reported
}
}
// Check that 1) we have a special error message for lack of annotation in this method and 2) treat
// `x` as implicitly nullable
class JavaLangEquals {
@Override
public boolean equals(Object x) {
// BAD: x can not be directly dereferenced without null comparison:
// it is implicitly nullable because Java requires `x.equals(null)` to work correctly.
// It is a common enough case to make the nullsafe support this specifically.
return x.toString() == "JavaLangEquals";
}
}
// Check multiple interfaces in the inheritance chain
interface NullableGetter {
@Nullable
String get();
}
interface NonNullableInterfaceGetterOK extends NullableGetter {
String get();
}
class NonNullableConcreteGetterOK implements NonNullableInterfaceGetterOK {
public String get() {
return "OK";
}
}
class NullableConcreteGetterBAD implements NonNullableInterfaceGetterOK {
@Nullable
public String get() {
return null;
}
}