Better support for substring in DFA

GitOrigin-RevId: 72a50f3948de1852583432d1b82c11da055bd2ec
This commit is contained in:
Tagir Valeev
2019-11-22 13:58:32 +07:00
committed by intellij-monorepo-bot
parent 476b3ff5bb
commit 7a16b10a90
3 changed files with 20 additions and 7 deletions

View File

@@ -251,13 +251,16 @@ class CustomMethodHandlers {
DfaValue qualifier = args.myQualifier;
DfaValue[] arguments = args.myArguments;
if (arguments.length < 1 || arguments.length > 2 || arguments[0] == null) return null;
LongRangeSet fromPos = state.getValueFact(arguments[0], DfaFactType.RANGE);
if (fromPos == null) return null;
DfaValue from = arguments[0];
DfaValue to = arguments.length == 1 ? STRING_LENGTH.createValue(factory, qualifier) : arguments[1];
DfaValue lengthVal = factory.getBinOpFactory().create(to, from, state, false, JavaTokenType.MINUS);
LongRangeSet resultLen = state.getValueFact(lengthVal, DfaFactType.RANGE);
if (resultLen == null) {
resultLen = LongRangeSet.point(0).fromRelation(RelationType.GE);
} else {
resultLen = resultLen.intersect(LongRangeSet.point(0).fromRelation(RelationType.GE));
}
LongRangeSet length = state.getValueFact(STRING_LENGTH.createValue(factory, qualifier), DfaFactType.RANGE);
LongRangeSet toPos = arguments.length == 1 ? length : state.getValueFact(arguments[1], DfaFactType.RANGE);
if (toPos == null) return null;
LongRangeSet resultLen = toPos.minus(fromPos, false)
.intersect(LongRangeSet.point(0).fromRelation(RelationType.GE));
if (length != null) {
resultLen = resultLen.intersect(length.fromRelation(RelationType.LE));
}

View File

@@ -850,6 +850,9 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
!applyUnboxedRelation(dfaLeft, dfaRight, relationType.isInequality())) {
return false;
}
if (relationType == RelationType.EQ && !applySpecialFieldEquivalence(dfaLeft, dfaRight)) {
return false;
}
if (dfaLeft instanceof DfaVariableValue) {
DfaVariableValue dfaVar = (DfaVariableValue)dfaLeft;
@@ -1183,7 +1186,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
private Couple<DfaValue> getSpecialEquivalencePair(DfaVariableValue left, DfaValue right) {
if (right instanceof DfaVariableValue) return null;
SpecialField field = SpecialField.fromQualifier(left);
if (field == null) return null;
if (field == null || field == SpecialField.UNBOX) return null;
DfaValue leftValue = field.createValue(myFactory, left);
DfaValue rightValue = field.createValue(myFactory, right);
return rightValue.equals(field.getDefaultValue(myFactory, false)) ? null : Couple.of(leftValue, rightValue);

View File

@@ -81,4 +81,11 @@ class StringSubstring {
if (<warning descr="Condition 's2.equals(\"\")' is always 'true'">s2.equals("")</warning>) {}
String s3 = s2.substring(0);
}
void testDiff(String s1, String s2, int pos) {
if (<warning descr="Condition 's1.substring(pos, pos+4).equals(\"xyz\")' is always 'false'">s1.substring(pos, pos+4).equals("xyz")</warning>) {}
if (s1.substring(pos, pos+4).equals(s2)) {
if (<warning descr="Condition 's2.length() != 4' is always 'false'">s2.length() != 4</warning>) {}
}
}
}