IDEA-224107 Separate "cast may produce CCE" and "cast will produce CCE"

GitOrigin-RevId: ffe650569937af9fc97b48066b4d4f72962bd737
This commit is contained in:
Tagir Valeev
2019-10-03 09:05:01 +00:00
committed by intellij-monorepo-bot
parent 6feb15bf5d
commit f31e1d6fc3
7 changed files with 23 additions and 11 deletions
@@ -701,7 +701,7 @@ public abstract class DataFlowInspectionBase extends AbstractBaseJavaLocalInspec
}
private void reportFailingCasts(ProblemReporter reporter, DataFlowInstructionVisitor visitor) {
for (PsiTypeCastExpression typeCast : visitor.getFailingCastExpressions()) {
visitor.getFailingCastExpressions().forKeyValue((typeCast, alwaysFails) -> {
PsiExpression operand = typeCast.getOperand();
PsiTypeElement castType = typeCast.getCastType();
assert castType != null;
@@ -710,8 +710,11 @@ public abstract class DataFlowInspectionBase extends AbstractBaseJavaLocalInspec
if (reporter.isOnTheFly()) {
fixes.add(createExplainFix(typeCast, new TrackingRunner.CastDfaProblemType()));
}
reporter.registerProblem(castType, InspectionsBundle.message("dataflow.message.cce", operand.getText()), fixes.toArray(LocalQuickFix.EMPTY_ARRAY));
}
String message = alwaysFails ?
InspectionsBundle.message("dataflow.message.cce.always", operand.getText()) :
InspectionsBundle.message("dataflow.message.cce", operand.getText());
reporter.registerProblem(castType, message, fixes.toArray(LocalQuickFix.EMPTY_ARRAY));
});
}
private void handleBranchingInstruction(ProblemReporter reporter,
@@ -1,7 +1,10 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.codeInspection.dataFlow;
import com.intellij.codeInspection.dataFlow.instructions.*;
import com.intellij.codeInspection.dataFlow.instructions.AssignInstruction;
import com.intellij.codeInspection.dataFlow.instructions.EndOfInitializerInstruction;
import com.intellij.codeInspection.dataFlow.instructions.Instruction;
import com.intellij.codeInspection.dataFlow.instructions.ReturnInstruction;
import com.intellij.codeInspection.dataFlow.value.*;
import com.intellij.codeInspection.util.OptionalUtil;
import com.intellij.openapi.application.Application;
@@ -18,6 +21,7 @@ import com.intellij.util.ThreeState;
import com.intellij.util.containers.ContainerUtil;
import com.siyeh.ig.callMatcher.CallMatcher;
import com.siyeh.ig.psiutils.TypeUtils;
import one.util.streamex.EntryStream;
import one.util.streamex.StreamEx;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -152,8 +156,8 @@ final class DataFlowInstructionVisitor extends StandardInstructionVisitor {
return myMethodReferenceResults;
}
StreamEx<PsiTypeCastExpression> getFailingCastExpressions() {
return StreamEx.ofKeys(myClassCastProblems, StateInfo::shouldReport);
EntryStream<PsiTypeCastExpression, Boolean> getFailingCastExpressions() {
return EntryStream.of(myClassCastProblems).filterValues(StateInfo::shouldReport).mapValues(StateInfo::alwaysFails);
}
Set<PsiElement> getMutabilityViolations(boolean receiver) {
@@ -328,6 +332,10 @@ final class DataFlowInstructionVisitor extends StandardInstructionVisitor {
// (e.g. if it's inside "if (var == null)" check after contract method invocation
return normalException || ephemeralException && !normalOk;
}
boolean alwaysFails() {
return (normalException || ephemeralException) && !normalOk;
}
}
private class ExpressionVisitor extends JavaElementVisitor {
@@ -17,7 +17,7 @@ public class Cce {
Object o = getObject();
if (o instanceof A) {
B b = (<warning descr="Casting 'o' to 'B' may produce 'ClassCastException'">B</warning>) o;
B b = (<warning descr="Casting 'o' to 'B' will produce 'ClassCastException' for any non-null value">B</warning>) o;
}
}
@@ -71,7 +71,7 @@ class CovariantReturn {
void testCast(Super s) {
if(s instanceof Sub) {
Integer i = (<warning descr="Casting 's.get()' to 'Integer' may produce 'ClassCastException'">Integer</warning>)s.get();
Integer i = (<warning descr="Casting 's.get()' to 'Integer' will produce 'ClassCastException' for any non-null value">Integer</warning>)s.get();
System.out.println(i);
}
}
@@ -2,11 +2,11 @@ class DataFlowBug {
public int add2(Object left, Object right) {
if (left != null && !(left instanceof String)) {
return ((<warning descr="Casting 'left' to 'String' may produce 'ClassCastException'">String</warning>) left).length();
return ((<warning descr="Casting 'left' to 'String' will produce 'ClassCastException' for any non-null value">String</warning>) left).length();
}
if (!(right instanceof String)) {
return ((<warning descr="Casting 'right' to 'String' may produce 'ClassCastException'">String</warning>) right).length();
return ((<warning descr="Casting 'right' to 'String' will produce 'ClassCastException' for any non-null value">String</warning>) right).length();
}
return 2;
@@ -61,7 +61,7 @@ public class StreamInlining {
void testIsInstanceIncomplete(List<?> objects) {
IntStream is = objects.stream()
.filter(String.class::isInstance)
.mapToInt(x -> (<warning descr="Casting 'x' to 'Integer' may produce 'ClassCastException'">Integer</warning>)x);
.mapToInt(x -> (<warning descr="Casting 'x' to 'Integer' will produce 'ClassCastException' for any non-null value">Integer</warning>)x);
objects.stream()
.filter(String.class::isInstance)
@@ -65,6 +65,7 @@ dataflow.message.npe.array.access.sure=Array access <code>#ref</code> #loc will
dataflow.message.npe.field.access.sure=Dereference of <code>#ref</code> #loc will produce <code>NullPointerException</code>
dataflow.message.npe.field.access=Dereference of <code>#ref</code> #loc may produce <code>NullPointerException</code>
dataflow.message.cce=Casting <code>{0}</code> to <code>#ref</code> #loc may produce <code>ClassCastException</code>
dataflow.message.cce.always=Casting <code>{0}</code> to <code>#ref</code> #loc will produce <code>ClassCastException</code> for any non-null value
dataflow.message.arraystore=Storing element of type <code>{0}</code> to array of <code>{1}</code> elements may produce <code>ArrayStoreException</code>
dataflow.message.redundant.instanceof=Condition <code>#ref</code> #loc is redundant and can be replaced with a null check
dataflow.message.contract.fail=The call to '#ref' always fails, according to its method contracts