DFA: Type cast processing fixes

This commit is contained in:
Tagir Valeev
2017-10-20 16:07:26 +07:00
parent b4cd3788e3
commit 3bc37fc21e
6 changed files with 35 additions and 10 deletions
@@ -306,7 +306,8 @@ public class StandardInstructionVisitor extends InstructionVisitor {
public DfaInstructionState[] visitTypeCast(TypeCastInstruction instruction, DataFlowRunner runner, DfaMemoryState memState) {
PsiType type = instruction.getCastTo();
final DfaValueFactory factory = runner.getFactory();
if (PsiUtil.resolveClassInType(type) != null && !memState.castTopOfStack(factory.createDfaType(type))) {
PsiType fromType = instruction.getCasted().getType();
if (fromType != null && type.isConvertibleFrom(fromType) && !memState.castTopOfStack(factory.createDfaType(type))) {
onInstructionProducesCCE(instruction);
}
@@ -16,10 +16,7 @@
package com.intellij.codeInspection.dataFlow;
import com.intellij.codeInspection.dataFlow.value.DfaPsiType;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiClassType;
import com.intellij.psi.PsiPrimitiveType;
import com.intellij.psi.PsiType;
import com.intellij.psi.*;
import com.intellij.util.containers.ContainerUtil;
import one.util.streamex.EntryStream;
import one.util.streamex.MoreCollectors;
@@ -84,7 +81,11 @@ public final class TypeConstraint {
@Nullable
public TypeConstraint withInstanceofValue(@NotNull DfaPsiType type) {
if (type.getPsiType() instanceof PsiPrimitiveType) return this;
PsiType psiType = type.getPsiType();
if (psiType instanceof PsiPrimitiveType || psiType instanceof PsiLambdaExpressionType ||
psiType instanceof PsiMethodReferenceType) {
return this;
}
if (!checkInstanceofValue(type)) {
return null;
@@ -84,9 +84,14 @@ public class DfaValueFactory {
@NotNull
public DfaPsiType createDfaType(@NotNull PsiType psiType) {
int dimensions = psiType.getArrayDimensions();
psiType = psiType.getDeepComponentType();
if (psiType instanceof PsiClassType) {
psiType = ((PsiClassType)psiType).rawType();
}
while (dimensions-- > 0) {
psiType = psiType.createArrayType();
}
DfaPsiType dfaType = myDfaTypes.get(psiType);
if (dfaType == null) {
myDfaTypes.put(psiType, dfaType = new DfaPsiType(psiType, myAssignableCache, myConvertibleCache));
@@ -205,9 +210,7 @@ public class DfaValueFactory {
final PsiJavaCodeReferenceElement thisQualifier = ((PsiQualifiedExpression)qualifier).getQualifier();
if (thisQualifier == null) return true;
final PsiClass innerMostClass = PsiTreeUtil.getParentOfType(refExpression, PsiClass.class);
if (innerMostClass == thisQualifier.resolve()) {
return true;
}
return innerMostClass == thisQualifier.resolve();
}
return false;
}
@@ -21,4 +21,24 @@ class Test {
}
}
}
void testUncheckedCast(List<String> list) {
List<Integer> l = (List<Integer>)(List<?>)list;
}
void testArrayCast(List<String>[] arr) {
List<Integer>[] arr2 = (List<Integer>[])(List<?>[])arr;
}
void testTwoObj(boolean b, Object o1, Object o2) {
if((b && o1 instanceof String) || o2 instanceof String) {
String x = (<warning descr="Casting '(b ? o1 : o2)' to 'String' may produce 'java.lang.ClassCastException'">String</warning>)(b ? o1 : o2);
}
}
void method(Object obj) {}
void testLambdaExpression() {
method((Runnable) () -> {});
}
}
@@ -206,4 +206,5 @@ public class DataFlowInspection8Test extends DataFlowInspectionTestCase {
doTest();
}
public void testCastInstanceOf() { doTest(); }
}
@@ -549,5 +549,4 @@ public class DataFlowInspectionTest extends DataFlowInspectionTestCase {
public void testTryWithResourceExpressions() { doTest(); }
public void testArrayStoreProblems() { doTest(); }
public void testCastInstanceOf() { doTest(); }
}