mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
TypeConstraint#union: smarter merge of supertypes
union("is X, Y; not SubX", "is SubX, Y") now produces "is X, Y"; before it was "is Y".
Fixes IDEA-184153 Smart-cast completion fails
This commit is contained in:
+14
-12
@@ -169,18 +169,8 @@ public final class TypeConstraint {
|
||||
Set<DfaPsiType> leftNotTypes = new HashSet<>(this.myNotInstanceofValues);
|
||||
Set<DfaPsiType> rightTypes = new HashSet<>(other.myInstanceofValues);
|
||||
Set<DfaPsiType> rightNotTypes = new HashSet<>(other.myNotInstanceofValues);
|
||||
for (Iterator<DfaPsiType> iterator = leftTypes.iterator(); iterator.hasNext(); ) {
|
||||
DfaPsiType type = iterator.next();
|
||||
if(rightNotTypes.remove(type)) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
for (Iterator<DfaPsiType> 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<DfaPsiType> leftTypes, Set<DfaPsiType> rightTypes, Set<DfaPsiType> rightNotTypes) {
|
||||
Set<DfaPsiType> addTypes = new HashSet<>();
|
||||
for (Iterator<DfaPsiType> 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<DfaPsiType> getInstanceofValues() {
|
||||
return Collections.unmodifiableSet(myInstanceofValues);
|
||||
|
||||
@@ -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<caret>
|
||||
}
|
||||
}
|
||||
}
|
||||
+4
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user