don't infer @Nullable from source when there's a contract about it (IDEA-137323)

This commit is contained in:
peter
2015-03-06 14:59:52 +01:00
parent b205caf9f3
commit e8fde4e27f
4 changed files with 33 additions and 3 deletions
@@ -166,7 +166,7 @@ public class DfaUtil {
if (rc == RunnerResult.OK) {
if (hasNulls.get()) {
return Nullness.NULLABLE;
return InferenceFromSourceUtil.suppressNullable(method) ? Nullness.UNKNOWN : Nullness.NULLABLE;
}
if (hasNotNulls.get() && !hasUnknowns.get()) {
return Nullness.NOT_NULL;
@@ -72,4 +72,15 @@ public class InferenceFromSourceUtil {
return false;
}
static boolean suppressNullable(PsiMethod method) {
if (method.getParameterList().getParametersCount() == 0) return false;
for (MethodContract contract : ControlFlowAnalyzer.getMethodContracts(method)) {
if (contract.returnValue == MethodContract.ValueConstraint.NULL_VALUE) {
return true;
}
}
return false;
}
}
@@ -117,7 +117,7 @@ public class NullityInference {
});
if (hasNulls.get()) {
return Nullness.NULLABLE;
return InferenceFromSourceUtil.suppressNullable(method) ? Nullness.UNKNOWN : Nullness.NULLABLE;
}
if (hasErrors.get() || hasUnknowns.get() || delegates.size() > 1) {
@@ -87,10 +87,29 @@ String bar() { return "z"; }
assert inferNullity(parse('Object foo() { return () -> { return null; }; }')) == NOT_NULL
}
void "test in presence of explicit null contract"() {
assert inferNullity(parse('''
@Contract("null->null")
Object foo(Object o) { if (o == null) return null; return 2; }
''')) == UNKNOWN
}
void "test in presence of inferred null contract"() {
assert inferNullity(parse('''
Object foo(Object o) { if (o == null) return null; return 2; }
''')) == UNKNOWN
}
void "test in presence of fail contract"() {
assert inferNullity(parse('''
@Contract("null->fail")
Object foo(Object o) { if (o == null) return o.hashCode(); return 2; }
''')) == NOT_NULL
}
protected abstract Nullness inferNullity(PsiMethod method)
protected PsiMethod parse(String method) {
return myFixture.addClass("final class Foo { $method }").methods[0]
return myFixture.addClass("import org.jetbrains.annotations.*; final class Foo { $method }").methods[0]
}
static class LightInferenceTest extends NullityInferenceFromSourceTestCase {