[java-dfa] Do not rely on class qualified name when checking for assignability/convertibility

Qualified name is absent for local classes, so it doesn't work correctly if local classes are inherited.
Also, as we already have PsiClass objects themselves, we can skip unnecessary resolve by qualified name.
Finally, we can go further in isConvertibleFrom and inline isInheritorOrSelf. This allows to deduplicate areElementsEquivalent, which is supposed to be symmetrical, so extra work is avoided.
Fixes IDEA-253169 Inheritors of local class cause false-positive 'ArrayStoreException' warning

GitOrigin-RevId: cbadd6e6e853ae2310427dd977187b61cf1b5d5e
This commit is contained in:
Tagir Valeev
2020-10-19 05:03:29 +00:00
committed by intellij-monorepo-bot
parent a3d72f8d4a
commit 538893bcd1
2 changed files with 11 additions and 7 deletions
@@ -359,9 +359,7 @@ public final class TypeConstraints {
public boolean isAssignableFrom(@NotNull Exact other) {
if (equals(other) || other instanceof Unresolved) return true;
if (other instanceof ExactClass) {
String name = myClass.getQualifiedName();
if (name == null) return false;
return InheritanceUtil.isInheritor(((ExactClass)other).myClass, name);
return InheritanceUtil.isInheritorOrSelf(((ExactClass)other).myClass, myClass, true);
}
return false;
}
@@ -379,10 +377,10 @@ public final class TypeConstraints {
if (myClass.isInterface() && otherClass.isInterface()) return true;
if (myClass.isInterface() && !otherClass.hasModifierProperty(PsiModifier.FINAL)) return true;
if (otherClass.isInterface() && !myClass.hasModifierProperty(PsiModifier.FINAL)) return true;
String otherName = otherClass.getQualifiedName();
String myName = myClass.getQualifiedName();
return otherName != null && InheritanceUtil.isInheritor(myClass, otherName) ||
myName != null && InheritanceUtil.isInheritor(otherClass, myName);
PsiManager manager = myClass.getManager();
return manager.areElementsEquivalent(myClass, otherClass) ||
otherClass.isInheritor(myClass, true) ||
myClass.isInheritor(otherClass, true);
}
return false;
}
@@ -2,6 +2,12 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.NotNull;
class ArrayStoreProblems {
void testLocalClass() {
abstract class Foo {}
Foo[] data = new Foo[1];
data[0] = new Foo() {};
}
void test(String[] args, Integer[] args2) {
Object[] arr = args;
arr[0] <warning descr="Storing element of type 'java.lang.Integer' to array of 'java.lang.String' elements will produce 'ArrayStoreException'">=</warning> 123;