From dd1196ae6b7327e8100ca26b0a37e442f239f6ed Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Wed, 28 Oct 2015 20:11:04 +0300 Subject: [PATCH] Condition analysis: left part of and (true condition) / or (false condition) is used for right part analysis #KT-8780 Fixed --- .../types/expressions/DataFlowAnalyzer.java | 5 ++- .../tests/smartCasts/comparisonUnderAnd.kt | 38 +++++++++++++++++++ .../tests/smartCasts/comparisonUnderAnd.txt | 3 ++ .../tests/smartCasts/complexComparison.kt | 22 +++++++++++ .../tests/smartCasts/complexComparison.txt | 3 ++ .../checkers/JetDiagnosticsTestGenerated.java | 12 ++++++ 6 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 compiler/testData/diagnostics/tests/smartCasts/comparisonUnderAnd.kt create mode 100644 compiler/testData/diagnostics/tests/smartCasts/comparisonUnderAnd.txt create mode 100644 compiler/testData/diagnostics/tests/smartCasts/complexComparison.kt create mode 100644 compiler/testData/diagnostics/tests/smartCasts/complexComparison.txt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DataFlowAnalyzer.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DataFlowAnalyzer.java index 80d6adf55d4..b805fcc9ec2 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DataFlowAnalyzer.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DataFlowAnalyzer.java @@ -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); } diff --git a/compiler/testData/diagnostics/tests/smartCasts/comparisonUnderAnd.kt b/compiler/testData/diagnostics/tests/smartCasts/comparisonUnderAnd.kt new file mode 100644 index 00000000000..c797a019214 --- /dev/null +++ b/compiler/testData/diagnostics/tests/smartCasts/comparisonUnderAnd.kt @@ -0,0 +1,38 @@ +fun foo(x : String?, y : String?) { + if (y != null && x == y) { + // Both not null + x.length + y.length + } + else { + x.length + y.length + } + if (y != null || x == y) { + x.length + y.length + } + else { + // y == null but x != y + x.length + y.length + } + if (y == null && x != y) { + // y == null but x != y + x.length + y.length + } + else { + x.length + y.length + } + if (y == null || x != y) { + x.length + y.length + } + else { + // Both not null + x.length + y.length + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/smartCasts/comparisonUnderAnd.txt b/compiler/testData/diagnostics/tests/smartCasts/comparisonUnderAnd.txt new file mode 100644 index 00000000000..c752ca6226b --- /dev/null +++ b/compiler/testData/diagnostics/tests/smartCasts/comparisonUnderAnd.txt @@ -0,0 +1,3 @@ +package + +public fun foo(/*0*/ x: kotlin.String?, /*1*/ y: kotlin.String?): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/smartCasts/complexComparison.kt b/compiler/testData/diagnostics/tests/smartCasts/complexComparison.kt new file mode 100644 index 00000000000..f9d0d54bc81 --- /dev/null +++ b/compiler/testData/diagnostics/tests/smartCasts/complexComparison.kt @@ -0,0 +1,22 @@ +fun foo(x: String?, y: String?, z: String?, w: String?) { + if (x != null && y != null && (x == z || y == z)) + z.length + else + z.length + if (x != null || y != null || (x != z && y != z)) + z.length + else + z.length + if (x == null || y == null || (x != z && y != z)) + z.length + else + z.length + if (x != null && y == x && z == y && w == z) + w.length + else + w.length + if ((x != null && y == x) || (z != null && y == z)) + y.length + else + y.length +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/smartCasts/complexComparison.txt b/compiler/testData/diagnostics/tests/smartCasts/complexComparison.txt new file mode 100644 index 00000000000..b935bc5fd2e --- /dev/null +++ b/compiler/testData/diagnostics/tests/smartCasts/complexComparison.txt @@ -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 diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java index 3373ae214f1..e87ff1a0553 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java @@ -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");