diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/TypeConstraint.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/TypeConstraint.java index 52143b02e20c..201930ee2d93 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/TypeConstraint.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/TypeConstraint.java @@ -169,18 +169,8 @@ public final class TypeConstraint { Set leftNotTypes = new HashSet<>(this.myNotInstanceofValues); Set rightTypes = new HashSet<>(other.myInstanceofValues); Set rightNotTypes = new HashSet<>(other.myNotInstanceofValues); - for (Iterator iterator = leftTypes.iterator(); iterator.hasNext(); ) { - DfaPsiType type = iterator.next(); - if(rightNotTypes.remove(type)) { - iterator.remove(); - } - } - for (Iterator iterator = rightTypes.iterator(); iterator.hasNext(); ) { - DfaPsiType type = iterator.next(); - if(leftNotTypes.remove(type)) { - iterator.remove(); - } - } + filter(leftTypes, rightTypes, rightNotTypes); + filter(rightTypes, leftTypes, leftNotTypes); TypeConstraint left = create(leftTypes, leftNotTypes); TypeConstraint right = create(rightTypes, rightNotTypes); if(left.isSuperStateOf(right)) return left; @@ -188,6 +178,18 @@ public final class TypeConstraint { return null; } + private static void filter(Set leftTypes, Set rightTypes, Set rightNotTypes) { + Set addTypes = new HashSet<>(); + for (Iterator iterator = leftTypes.iterator(); iterator.hasNext(); ) { + DfaPsiType type = iterator.next(); + if(rightNotTypes.remove(type)) { + iterator.remove(); + StreamEx.of(rightTypes).filter(t -> t.isAssignableFrom(type)).into(addTypes); + } + } + leftTypes.addAll(addTypes); + } + @NotNull public Set getInstanceofValues() { return Collections.unmodifiableSet(myInstanceofValues); diff --git a/java/java-tests/testData/codeInsight/completion/normal/ComplexInstanceOfDfa.java b/java/java-tests/testData/codeInsight/completion/normal/ComplexInstanceOfDfa.java new file mode 100644 index 000000000000..a00d90dd8407 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/ComplexInstanceOfDfa.java @@ -0,0 +1,25 @@ +import java.math.BigInteger; +import java.util.function.Function; + +class Test { + interface X { + void methodFromX(); + void methodFromX2(); + } + + interface Y { + void methodFromY(); + void methodFromY2(); + } + + interface Z extends X {} + + void test(Object obj) { + if(obj instanceof Z && Math.random() > 0.5) { + return; + } + if(obj instanceof X && obj instanceof Y) { + obj.method + } + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/NormalCompletionDfaTest.groovy b/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/NormalCompletionDfaTest.groovy index bf6749760dda..a3f5d1a31ad7 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/NormalCompletionDfaTest.groovy +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/NormalCompletionDfaTest.groovy @@ -55,6 +55,10 @@ class NormalCompletionDfaTest extends NormalCompletionTestCase { void testNoUnnecessaryCastDfa() { doTest() } void testNoUnnecessaryCastRawDfa() { doTest() } void testInstanceOfAfterFunction() { doTest() } + void testComplexInstanceOfDfa() { + configureByTestName() + myFixture.assertPreferredCompletionItems 0, 'methodFromX', 'methodFromX2', 'methodFromY', 'methodFromY2' + } void testCastTwice() { configureByTestName()