contract checker: relax fail result validation to accept every call as a potential hazard, and don't continue with dfa

This commit is contained in:
peter
2014-10-01 20:09:11 +02:00
parent eb332c2127
commit be5e2c5a5a
2 changed files with 14 additions and 5 deletions
@@ -38,7 +38,6 @@ class ContractChecker extends DataFlowRunner {
private final Set<PsiElement> myViolations = ContainerUtil.newHashSet();
private final Set<PsiElement> myNonViolations = ContainerUtil.newHashSet();
private final Set<PsiElement> myFailures = ContainerUtil.newHashSet();
private final Set<PsiElement> myCalls = ContainerUtil.newHashSet();
ContractChecker(PsiMethod method, PsiCodeBlock body, MethodContract contract, final boolean onTheFly) {
super(body);
@@ -105,11 +104,13 @@ class ContractChecker extends DataFlowRunner {
}
if (instruction instanceof MethodCallInstruction &&
((MethodCallInstruction)instruction).getMethodType() == MethodCallInstruction.MethodType.REGULAR_METHOD_CALL) {
ContainerUtil.addIfNotNull(myCalls, ((MethodCallInstruction)instruction).getCallExpression());
((MethodCallInstruction)instruction).getMethodType() == MethodCallInstruction.MethodType.REGULAR_METHOD_CALL &&
myContract.returnValue == MethodContract.ValueConstraint.THROW_EXCEPTION) {
ContainerUtil.addIfNotNull(myFailures, ((MethodCallInstruction)instruction).getCallExpression());
return DfaInstructionState.EMPTY_ARRAY;
}
return super.acceptInstruction(visitor, instructionState);
return super.acceptInstruction(visitor, instructionState);
}
@@ -125,7 +126,7 @@ class ContractChecker extends DataFlowRunner {
for (PsiElement element : myFailures) {
errors.put(element, "Contract clause '" + myContract + "' is violated: exception might be thrown instead of returning " + myContract.returnValue);
}
} else if (myFailures.isEmpty() && errors.isEmpty() && myCalls.isEmpty()) {
} else if (myFailures.isEmpty() && errors.isEmpty()) {
PsiIdentifier nameIdentifier = myMethod.getNameIdentifier();
errors.put(nameIdentifier != null ? nameIdentifier : myMethod,
"Contract clause '" + myContract + "' is violated: no exception is thrown");
@@ -25,6 +25,14 @@ class Foo {
failNatively();
}
}
@Contract("null->fail")
public Object assertNotNull(Object o) {
if (o == null) {
failNatively();
}
return o;
}
native void failNatively();