mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
dfa: store CCE state in visitor, not runner: the latter is reused which can result in multiple warning
This commit is contained in:
+11
-10
@@ -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) {
|
||||
|
||||
-27
@@ -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(); }
|
||||
|
||||
Reference in New Issue
Block a user