diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/TrackingRunner.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/TrackingRunner.java index a76d7cd97474..e6407d4c4ccc 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/TrackingRunner.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/TrackingRunner.java @@ -163,12 +163,15 @@ public class TrackingRunner extends StandardDataFlowRunner { Cause for "modifying an immutable collection" Cause for "Collection is always empty" (separate inspection now) TODO: 2. Describe causes in more cases: - Warning caused by contract + Warning caused by complex contracts Warning caused by CustomMethodHandler Warning caused by polyadic math Warning caused by unary minus + Warning caused by string concatenation + Warning caused by java.lang.Void nullability + Warning caused by getClass() equality + Warning caused by inliners TODO: 3. Check how it works with: - Inliners (notably: Stream API) Boxed numbers */ @Nullable @@ -356,9 +359,22 @@ public class TrackingRunner extends StandardDataFlowRunner { if (children.isEmpty()) { ((PossibleExecutionDfaProblemType)mergePoint.myProblem).myComplete = false; } + List mergeChildren = mergePoint.myChildren; for (CauseItem child : children) { - if (!mergePoint.myChildren.contains(child)) { - mergePoint.myChildren.add(child); + if (!mergeChildren.contains(child)) { + boolean merged = false; + for (int i = 0; i < mergeChildren.size(); i++) { + CauseItem mergeChild = mergeChildren.get(i); + CauseItem result = mergeChild.merge(child); + if (result != null) { + mergeChildren.set(i, result); + merged = true; + break; + } + } + if (!merged) { + mergeChildren.add(child); + } } } return true; diff --git a/java/java-tests/testData/inspection/dataFlow/tracker/MergeOnAnd.java b/java/java-tests/testData/inspection/dataFlow/tracker/MergeOnAnd.java new file mode 100644 index 000000000000..ca9301b7c8ae --- /dev/null +++ b/java/java-tests/testData/inspection/dataFlow/tracker/MergeOnAnd.java @@ -0,0 +1,36 @@ +/* +Value is always false (bar.equals("Asdasdd") && asdsa.length() == 12; line#32) + One of the following happens: + Operand #1 of &&-chain is false (bar.equals("Asdasdd"); line#32) + According to hard-coded contract, method 'equals' returns 'false' value when this != parameter (equals; line#32) + One of the following happens: + 'bar' was assigned (=; line#25) + Values cannot be equal because "asdbar".length != "Asdasdd".length + Left operand is 6 (foo + "bar"; line#25) + and right operand is 7 ("Asdasdd"; line#32) + or 'bar' was assigned (=; line#27) + Values cannot be equal because "asdbaz".length != "Asdasdd".length + Left operand is 6 (foo + "baz"; line#27) + and right operand is 7 ("Asdasdd"; line#32) + or operand #2 of &&-chain is false (asdsa.length() == 12; line#32) + Left operand is in {0..3} (asdsa.length(); line#32) + Range is known from line #32 (bar.equals("Asdasdd"); line#32) + */ +class A + public A(String asdsa) { + String foo = "asd"; + String bar; + + if (asdsa.length() > 4) { + bar = foo + "bar"; + } else if (asdsa.length() >3) { + bar = foo + "baz"; + } else { + bar = "Asdasdd"; + } + + if (bar.equals("Asdasdd") && asdsa.length() == 12) { + System.out.println("asd"); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionTrackerTest.java b/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionTrackerTest.java index 031585432770..1951c4987ed3 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionTrackerTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionTrackerTest.java @@ -179,4 +179,5 @@ public class DataFlowInspectionTrackerTest extends LightJavaCodeInsightFixtureTe public void testFinalFieldInitializedCtor() { doTest(); } public void testEqualsNull() { doTest(); } public void testEnumCompare() { doTest(); } + public void testMergeOnAnd() { doTest(); } }