[java-dfa] Check fail result for constructors

GitOrigin-RevId: ce02739377b5d4fc8c2800e6450163bacef80152
This commit is contained in:
Tagir Valeev
2020-11-26 02:54:58 +00:00
committed by intellij-monorepo-bot
parent 2665266a81
commit 301c703f5d
4 changed files with 28 additions and 11 deletions
@@ -1688,6 +1688,15 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
addInstruction(new MethodCallInstruction(expression, myFactory.createValue(expression), contracts));
anchor = expression;
}
processFailResult(contracts, anchor);
addMethodThrows(method, anchor);
if (expression != null) {
addNullCheck(expression);
}
}
private void processFailResult(List<? extends MethodContract> contracts, PsiExpression anchor) {
if (contracts.stream().anyMatch(c -> c.getReturnValue().isFail())) {
// if a contract resulted in 'fail', handle it
addInstruction(new DupInstruction());
@@ -1699,11 +1708,6 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
ifNotFail.setOffset(myCurrentFlow.getInstructionCount());
}
addMethodThrows(method, anchor);
if (expression != null) {
addNullCheck(expression);
}
}
@Override
@@ -1792,7 +1796,9 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
addConditionalErrorThrow();
DfaValue precalculatedNewValue = getPrecalculatedNewValue(expression);
List<? extends MethodContract> contracts = constructor == null ? Collections.emptyList() : JavaMethodContractUtil.getMethodContracts(constructor);
addInstruction(new MethodCallInstruction(expression, precalculatedNewValue, DfaUtil.addRangeContracts(constructor, contracts)));
contracts = DfaUtil.addRangeContracts(constructor, contracts);
addInstruction(new MethodCallInstruction(expression, precalculatedNewValue, contracts));
processFailResult(contracts, expression);
addMethodThrows(constructor, expression);
}
@@ -7,11 +7,11 @@ class CandidateInfo<T> {
}
static void test() {
new <warning descr="The call to 'CandidateInfo' always fails, according to its method contracts">CandidateInfo</warning>(null, true, false);
new <warning descr="The call to 'CandidateInfo' always fails, according to its method contracts">CandidateInfo</warning>(null, true, true);
if (Math.random() > 0.5) new <warning descr="The call to 'CandidateInfo' always fails, according to its method contracts">CandidateInfo</warning>(null, true, false);
if (Math.random() > 0.5) new <warning descr="The call to 'CandidateInfo' always fails, according to its method contracts">CandidateInfo</warning>(null, true, true);
new CandidateInfo(null, false, true);
new CandidateInfo(new Object(), true, true);
new CandidateInfo(new Object(), false, true);
if (Math.random() > 0.5) new CandidateInfo(null, false, true);
if (Math.random() > 0.5) new CandidateInfo(new Object(), true, true);
if (Math.random() > 0.5) new CandidateInfo(new Object(), false, true);
}
}
@@ -0,0 +1,10 @@
import java.util.*;
public class PresizedList {
void test(int size) {
List<String> list = new ArrayList<>(size);
for (int i = 0; <warning descr="Condition 'i < list.size()' is always 'false'">i < <warning descr="Result of 'list.size()' is always '0'">list.size()</warning></warning>; i++) {
list.add(i, "");
}
}
}
@@ -686,4 +686,5 @@ public class DataFlowInspectionTest extends DataFlowInspectionTestCase {
public void testInferenceInPrivateOrLocalClass() { doTest(); }
public void testArraysCopyOf() { doTest(); }
public void testArrayNegativeSize() { doTest(); }
public void testPresizedList() { doTest(); }
}