dfa: store CCE state in visitor, not runner: the latter is reused which can result in multiple warning

This commit is contained in:
peter
2015-09-01 21:48:59 +02:00
parent d811626884
commit bf4a3805e0
4 changed files with 33 additions and 37 deletions
@@ -196,7 +196,7 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool {
ProblemsHolder holder,
StandardDataFlowRunner dfaRunner,
Collection<DfaMemoryState> initialStates, final boolean onTheFly) {
final DataFlowInstructionVisitor visitor = new DataFlowInstructionVisitor(dfaRunner);
final DataFlowInstructionVisitor visitor = new DataFlowInstructionVisitor();
final RunnerResult rc = dfaRunner.analyzeMethod(scope, visitor, IGNORE_ASSERT_STATEMENTS, initialStates);
if (rc == RunnerResult.OK) {
createDescription(dfaRunner, holder, visitor, onTheFly, scope);
@@ -257,7 +257,7 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool {
protected void addSurroundWithIfFix(PsiExpression qualifier, List<LocalQuickFix> fixes, boolean onTheFly) {
}
private void createDescription(StandardDataFlowRunner runner, ProblemsHolder holder, DataFlowInstructionVisitor visitor, final boolean onTheFly, PsiElement scope) {
private void createDescription(StandardDataFlowRunner runner, ProblemsHolder holder, final DataFlowInstructionVisitor visitor, final boolean onTheFly, PsiElement scope) {
Pair<Set<Instruction>, Set<Instruction>> constConditions = runner.getConstConditionalExpressions();
Set<Instruction> trueSet = constConditions.getFirst();
Set<Instruction> falseSet = constConditions.getSecond();
@@ -265,8 +265,13 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool {
ArrayList<Instruction> allProblems = new ArrayList<Instruction>();
allProblems.addAll(trueSet);
allProblems.addAll(falseSet);
allProblems.addAll(runner.getCCEInstructions());
allProblems.addAll(StandardDataFlowRunner.getRedundantInstanceofs(runner, visitor));
allProblems.addAll(visitor.myCCEInstructions);
allProblems.addAll(ContainerUtil.filter(runner.getInstructions(), new Condition<Instruction>() {
@Override
public boolean value(Instruction instruction1) {
return instruction1 instanceof InstanceofInstruction && visitor.isInstanceofRedundant((InstanceofInstruction)instruction1);
}
}));
HashSet<PsiElement> reportedAnchors = new HashSet<PsiElement>();
for (PsiElement element : visitor.getProblems(NullabilityProblem.callNPE)) {
@@ -795,17 +800,13 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool {
}
private static class DataFlowInstructionVisitor extends StandardInstructionVisitor {
private final StandardDataFlowRunner myRunner;
private final MultiMap<NullabilityProblem, PsiElement> myProblems = new MultiMap<NullabilityProblem, PsiElement>();
private final Map<Pair<NullabilityProblem, PsiElement>, StateInfo> myStateInfos = ContainerUtil.newHashMap();
private DataFlowInstructionVisitor(StandardDataFlowRunner runner) {
myRunner = runner;
}
private final Set<Instruction> myCCEInstructions = ContainerUtil.newHashSet();
@Override
protected void onInstructionProducesCCE(TypeCastInstruction instruction) {
myRunner.onInstructionProducesCCE(instruction);
myCCEInstructions.add(instruction);
}
Collection<PsiElement> getProblems(final NullabilityProblem kind) {
@@ -24,15 +24,7 @@
*/
package com.intellij.codeInspection.dataFlow;
import com.intellij.codeInspection.dataFlow.instructions.InstanceofInstruction;
import com.intellij.codeInspection.dataFlow.instructions.Instruction;
import org.jetbrains.annotations.NotNull;
import java.util.HashSet;
import java.util.Set;
public class StandardDataFlowRunner extends DataFlowRunner {
private final Set<Instruction> myCCEInstructions = new HashSet<Instruction>();
public StandardDataFlowRunner() {
this(false, true);
@@ -40,23 +32,4 @@ public class StandardDataFlowRunner extends DataFlowRunner {
public StandardDataFlowRunner(boolean unknownMembersAreNullable, boolean honorFieldInitializers) {
super(unknownMembersAreNullable, honorFieldInitializers);
}
public void onInstructionProducesCCE(Instruction instruction) {
myCCEInstructions.add(instruction);
}
@NotNull public Set<Instruction> getCCEInstructions() {
return myCCEInstructions;
}
@NotNull public static Set<Instruction> getRedundantInstanceofs(final DataFlowRunner runner, StandardInstructionVisitor visitor) {
HashSet<Instruction> result = new HashSet<Instruction>(1);
for (Instruction instruction : runner.getInstructions()) {
if (instruction instanceof InstanceofInstruction && visitor.isInstanceofRedundant((InstanceofInstruction)instruction)) {
result.add(instruction);
}
}
return result;
}
}
@@ -0,0 +1,21 @@
class X {
public static void main(Object result) {
final boolean varargs = result instanceof Intf;
new Runnable() {
public void run() { }
};
Intf a = (<warning descr="Casting 'result' to 'Intf' may produce 'java.lang.ClassCastException'">Intf</warning>)result;
}
public static void main2(Object result) {
final boolean varargs = result instanceof Intf;
if (!varargs) return;
new Runnable() {
public void run() { }
};
if (<warning descr="Condition 'result instanceof Intf' is always 'true'">result instanceof Intf</warning>) {
System.out.println();
}
}
}
interface Intf {}
@@ -241,6 +241,7 @@ public class DataFlowInspectionTest extends LightCodeInsightFixtureTestCase {
public void testBoxingImpliesNotNull() { doTest(); }
public void testLargeIntegersAreNotEqualWhenBoxed() { doTest(); }
public void testNoGenericCCE() { doTest(); }
public void testDoubleCCEWarning() { doTest(); }
public void testLongCircuitOperations() { doTest(); }
public void testUnconditionalForLoop() { doTest(); }
public void testAnonymousMethodIndependence() { doTest(); }