|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
[nullsafe] Prepare to introduce gradual mode: split tests
Summary:
In next diff, we are going to introduce a new mode of nullsafe
(gradual). For testing, we are going to employ the strategy used by jvillard
for Pulse.
In this diff we split tests into two subfolders, one for the default and one for the gradual
mode.
We are planning to make the gradual mode default eventually. For that, most
new features will make sense for gradual mode, and we will mostly evolve
tests for that mode.
As for 'default' mode, we need to preserve tests mostly to ensure we don't introduce
regressions.
Occasionally, we might make changes that make sense for both modes, in
this (expected relatively rare) cases we will make changes to both set
of tests.
An alternative strategy would be to have two sets of issues.exp files,
one for gradual and one for default mode. This has an advantage of each
java file to be always tested twice, but disadvantage is that it will be
harder to write meaningful test code so that it makes sense for both
modes simultaneously.
Reviewed By: ngorogiannis
Differential Revision: D17156724
fbshipit-source-id: a92a9208f
5 years ago
|
|
|
package codetoanalyze.java.nullsafe_default;
|
|
|
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|