[java-dfa] IDEA-365304 Data flow analysis: ignore instanceof statements if operand type or check type is not fully resolved

GitOrigin-RevId: fad95d5a40cccc2b2a36d1a2180c3ac08b70fa5b
This commit is contained in:
Tagir Valeev
2025-01-03 10:57:09 +00:00
committed by intellij-monorepo-bot
parent 7af824e45c
commit 0de99ed319
7 changed files with 60 additions and 6 deletions
@@ -1209,7 +1209,9 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
checkType = TypeConversionUtil.erasure(checkType);
if (patternType == null ||
((checkType instanceof PsiPrimitiveType || patternType instanceof PsiPrimitiveType) &&
(!PsiUtil.isAvailable(JavaFeature.PRIMITIVE_TYPES_IN_PATTERNS, context) || !TypeConversionUtil.areTypesConvertible(checkType, patternType)))) {
(!PsiUtil.isAvailable(JavaFeature.PRIMITIVE_TYPES_IN_PATTERNS, context) || !TypeConversionUtil.areTypesConvertible(checkType, patternType))) ||
(checkType instanceof PsiClassType ct && ct.resolve() == null) ||
(patternType instanceof PsiClassType pt && pt.resolve() == null)) {
addInstruction(new PopInstruction());
pushUnknown();
return;
@@ -1,7 +1,7 @@
@Target(ElementType.TYPE_USE)
@interface N {}
class M {
void m(Oject o) {
void m(Object o) {
if (o instanceof @N String) {
o.castvar<caret>
}
@@ -1,7 +1,7 @@
@Target(ElementType.TYPE_USE)
@interface N {}
class M {
void m(Oject o) {
void m(Object o) {
if (o instanceof @N String) {
String s = (String) o;<caret>
}
@@ -4,7 +4,7 @@ public enum Test {
void test() {
Integer code = getCode();
switch (code) {
case <error descr="Constant expression, pattern or null is required"><warning descr="Switch label 'VALUE.value()' is the only reachable in the whole switch">VALUE.<error descr="Cannot resolve symbol 'value'">value</error>()</warning></error><EOLError descr="':' or '->' expected"></EOLError>
case <error descr="Constant expression, pattern or null is required">VALUE.<error descr="Cannot resolve symbol 'value'">value</error>()</error><EOLError descr="':' or '->' expected"></EOLError>
}
if (code == VALUE.value()) {
getCode();
@@ -0,0 +1,51 @@
public class InstanceOfUnresolvedType {
void test(Object o) {
int i = 0;
if (o instanceof <error descr="Cannot resolve symbol 'Unresolved'">Unresolved</error>) {
i = 1;
}
else if (o instanceof <error descr="Cannot resolve symbol 'Unresolved2'">Unresolved2</error>) {
i = 2;
}
else {
i = 3;
}
if (<warning descr="Condition 'i == 0' is always 'false'">i == 0</warning>) {
}
else if (i == 1) {
}
else if (i == 2) {
}
else if (<warning descr="Condition 'i == 3' is always 'true'">i == 3</warning>) {
}
}
void test2(<error descr="Cannot resolve symbol 'Unresolved'">Unresolved</error> u) {
int i = 0;
if (<error descr="Inconvertible types; cannot cast 'Unresolved' to 'java.lang.CharSequence'">u instanceof CharSequence cs</error>) {
i = 1;
}
else if (<error descr="Inconvertible types; cannot cast 'Unresolved' to 'java.lang.Number'">u instanceof Number n</error>) {
i = 2;
}
else {
i = 3;
}
if (<warning descr="Condition 'i == 0' is always 'false'">i == 0</warning>) {
}
else if (i == 1) {
}
else if (i == 2) {
}
else if (<warning descr="Condition 'i == 3' is always 'true'">i == 3</warning>) {
}
}
}
@@ -131,6 +131,7 @@ public class DataFlowInspection21Test extends DataFlowInspectionTestCase {
public void testArrayElementWrappedInPureMethod() { doTest(); }
public void testArrayAddedIntoCollection() { doTest(); }
public void testInstanceOfUnresolvedType() { doTest(); }
public void testInstanceOfPatternAffectNullity() { doTest(); }
@@ -8,7 +8,7 @@ class A {
val bindingContext: BindingContext =
AnalyzerFacadeWithCache.analyzeFileWithCache(element.getContainingJetFile()).getBindingContext()
val declarationDescriptor: DeclarationDescriptor? =
val declarationDescriptor: DeclarationDescriptor =
bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, element)
if (declarationDescriptor is CallableMemberDescriptor) {
val containingDescriptor: DeclarationDescriptor? = declarationDescriptor.getContainingDeclaration()
@@ -25,7 +25,7 @@ class A {
assert(
element is PsiMethod
) { "Method accepts only kotlin functions/properties and java methods, but '" + element.getText() + "' was found" }
return JetRefactoringUtil.formatPsiMethod(element as PsiMethod, true, false)
return JetRefactoringUtil.formatPsiMethod(element as PsiMethod?, true, false)
}
protected override fun getDimensionServiceKey(): String {