IDEA-197241: fixed false-positive when variable type is narrowed from Object to String

This commit is contained in:
Tagir Valeev
2018-08-14 01:20:04 +07:00
parent 004c77c6e8
commit 895dd41e7a
3 changed files with 39 additions and 3 deletions
@@ -675,12 +675,32 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
return false;
}
setVariableState((DfaVariableValue)value, newState);
if (newState.getTypeConstraint().isExact(CommonClassNames.JAVA_LANG_STRING) &&
!newState.getTypeConstraint().equals(oldState.getTypeConstraint())) {
// Type is narrowed to java.lang.String: we consider String equivalence by content,
// but other object types by reference, so we need to remove distinct pairs, if any.
convertReferenceEqualityToValueEquality(value);
}
updateEquivalentVariables((DfaVariableValue)value, newState);
return updateEqClassesByState((DfaVariableValue)value);
}
return true;
}
private void convertReferenceEqualityToValueEquality(DfaValue value) {
int id = value.getID();
int[] indices = myIdToEqClassesIndices.get(id);
for (int index : indices) {
for (Iterator<DistinctPairSet.DistinctPair> iterator = myDistinctClasses.iterator(); iterator.hasNext(); ) {
DistinctPairSet.DistinctPair pair = iterator.next();
EqClass otherClass = pair.getOtherClass(index);
if (otherClass != null && otherClass.findConstant(false) != getFactory().getConstFactory().getNull()) {
iterator.remove();
}
}
}
}
private boolean updateEqClassesByState(DfaVariableValue value) {
if (DfaNullability.isNotNull(getVariableState(value).myFactMap)) {
return applyRelation(value, getFactory().getConstFactory().getNull(), true);
@@ -68,6 +68,8 @@ public abstract class TypeConstraint {
public abstract boolean isExact();
public abstract boolean isExact(String typeName);
static final class Exact extends TypeConstraint {
final @NotNull DfaPsiType myType;
@@ -159,6 +161,11 @@ public abstract class TypeConstraint {
return true;
}
@Override
public boolean isExact(String typeName) {
return myType.getPsiType().equalsToText(typeName);
}
@Override
public int hashCode() {
return myType.hashCode();
@@ -404,6 +411,11 @@ public abstract class TypeConstraint {
return false;
}
@Override
public boolean isExact(String typeName) {
return false;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
@@ -42,10 +42,14 @@ class StringEquality {
}
boolean compare(Object a, Object b) {
if(a == b) return true;
if(a == b) {
if(a instanceof String) {
return <warning descr="Result of '((String)a).equals(b)' is always 'true'">((String)a).equals(b)</warning>;
}
return true;
}
if(a instanceof String && b instanceof String) {
// false-positive
return <warning descr="Result of '((String)a).equals((String)b)' is always 'false'">((String)a).equals((String)b)</warning>;
return ((String)a).equals(b);
}
return false;
}