Condition analysis: left part of and (true condition) / or (false condition) is used for right part analysis #KT-8780 Fixed

This commit is contained in:
Mikhail Glukhikh
2015-10-28 20:11:04 +03:00
parent 12103d19d2
commit dd1196ae6b
6 changed files with 82 additions and 1 deletions
@@ -85,8 +85,11 @@ public class DataFlowAnalyzer {
DataFlowInfo dataFlowInfo = extractDataFlowInfoFromCondition(expression.getLeft(), conditionValue, context);
KtExpression expressionRight = expression.getRight();
if (expressionRight != null) {
DataFlowInfo rightInfo = extractDataFlowInfoFromCondition(expressionRight, conditionValue, context);
boolean and = operationToken == KtTokens.ANDAND;
DataFlowInfo rightInfo = extractDataFlowInfoFromCondition(
expressionRight, conditionValue,
and == conditionValue ? context.replaceDataFlowInfo(dataFlowInfo) : context
);
if (and == conditionValue) { // this means: and && conditionValue || !and && !conditionValue
dataFlowInfo = dataFlowInfo.and(rightInfo);
}
@@ -0,0 +1,38 @@
fun foo(x : String?, y : String?) {
if (y != null && x == y) {
// Both not null
<!DEBUG_INFO_SMARTCAST!>x<!>.length
<!DEBUG_INFO_SMARTCAST!>y<!>.length
}
else {
x<!UNSAFE_CALL!>.<!>length
y<!UNSAFE_CALL!>.<!>length
}
if (y != null || x == y) {
x<!UNSAFE_CALL!>.<!>length
y<!UNSAFE_CALL!>.<!>length
}
else {
// y == null but x != y
<!DEBUG_INFO_SMARTCAST!>x<!>.length
y<!UNSAFE_CALL!>.<!>length
}
if (y == null && x != y) {
// y == null but x != y
<!DEBUG_INFO_SMARTCAST!>x<!>.length
y<!UNSAFE_CALL!>.<!>length
}
else {
x<!UNSAFE_CALL!>.<!>length
y<!UNSAFE_CALL!>.<!>length
}
if (y == null || x != y) {
x<!UNSAFE_CALL!>.<!>length
y<!UNSAFE_CALL!>.<!>length
}
else {
// Both not null
<!DEBUG_INFO_SMARTCAST!>x<!>.length
<!DEBUG_INFO_SMARTCAST!>y<!>.length
}
}
@@ -0,0 +1,3 @@
package
public fun foo(/*0*/ x: kotlin.String?, /*1*/ y: kotlin.String?): kotlin.Unit
@@ -0,0 +1,22 @@
fun foo(x: String?, y: String?, z: String?, w: String?) {
if (x != null && y != null && (x == z || y == z))
<!DEBUG_INFO_SMARTCAST!>z<!>.length
else
z<!UNSAFE_CALL!>.<!>length
if (x != null || y != null || (x != z && y != z))
z<!UNSAFE_CALL!>.<!>length
else
z<!UNSAFE_CALL!>.<!>length
if (x == null || y == null || (x != z && y != z))
z<!UNSAFE_CALL!>.<!>length
else
<!DEBUG_INFO_SMARTCAST!>z<!>.length
if (x != null && y == x && z == y && w == z)
<!DEBUG_INFO_SMARTCAST!>w<!>.length
else
w<!UNSAFE_CALL!>.<!>length
if ((x != null && y == x) || (z != null && y == z))
<!DEBUG_INFO_SMARTCAST!>y<!>.length
else
y<!UNSAFE_CALL!>.<!>length
}
@@ -0,0 +1,3 @@
package
public fun foo(/*0*/ x: kotlin.String?, /*1*/ y: kotlin.String?, /*2*/ z: kotlin.String?, /*3*/ w: kotlin.String?): kotlin.Unit
@@ -14298,6 +14298,18 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("comparisonUnderAnd.kt")
public void testComparisonUnderAnd() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/smartCasts/comparisonUnderAnd.kt");
doTest(fileName);
}
@TestMetadata("complexComparison.kt")
public void testComplexComparison() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/smartCasts/complexComparison.kt");
doTest(fileName);
}
@TestMetadata("dataFlowInfoForArguments.kt")
public void testDataFlowInfoForArguments() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/smartCasts/dataFlowInfoForArguments.kt");