caller hierarchy: in case of bound generics do not filter out bounds-related usages to fix another case in IDEA-275145 result of call hierarchy is not correct

GitOrigin-RevId: c713a96efd775a301439c4e6d5502d3827477fcb
This commit is contained in:
Alexey Kudravtsev
2022-01-12 16:50:30 +00:00
committed by intellij-monorepo-bot
parent 37c4505bd5
commit ed360ef370
4 changed files with 38 additions and 2 deletions
@@ -105,8 +105,7 @@ public final class CallerMethodsTreeStructure extends HierarchyTreeStructure {
if (receiverClass != null
&& expectedQualifierClass != null
&& !InheritanceUtil.isInheritorOrSelf(expectedQualifierClass, receiverClass, true)
&& !InheritanceUtil.isInheritorOrSelf(receiverClass, expectedQualifierClass, true)
&& !areClassesRelated(expectedQualifierClass, receiverClass)
) {
// ignore impossible candidates. E.g. when A < B,A < C and we invoked call hierarchy for method in C we should filter out methods in B because B and C are assignment-incompatible
return true;
@@ -130,6 +129,22 @@ public final class CallerMethodsTreeStructure extends HierarchyTreeStructure {
.map(e -> new CallHierarchyNodeDescriptor(myProject, nodeDescriptor, e, false, false)).toArray();
}
private static boolean areClassesRelated(@NotNull PsiClass expectedQualifierClass, @NotNull PsiClass receiverClass) {
if (InheritanceUtil.isInheritorOrSelf(expectedQualifierClass, receiverClass, true)
|| InheritanceUtil.isInheritorOrSelf(receiverClass, expectedQualifierClass, true)) {
return true;
}
if (receiverClass instanceof PsiTypeParameter) {
// in case of "T extends S", it should be related to SImpl, even though T is not superclass of SImpl
for (PsiClass receiverExtends : receiverClass.getSupers()) {
if (areClassesRelated(expectedQualifierClass, receiverExtends)) {
return true;
}
}
}
return false;
}
private static boolean isLocalOrAnonymousClass(PsiMember enclosingElement) {
return enclosingElement instanceof PsiClass && ((PsiClass)enclosingElement).getQualifiedName() == null;
}
@@ -0,0 +1,15 @@
package p;
interface Board {
int getCount();
}
class BoardImpl implements Board {
@Override
public int getCount() {return 0;}
}
class King<B extends Board> {
B board;
boolean isLast() {
return board.getCount() == 1;
}
}
@@ -0,0 +1,3 @@
<node text="BoardImpl.getCount() (p)" base="true">
<node text="King.isLast() (p)"/>
</node>
@@ -144,4 +144,7 @@ public class JavaCallHierarchyTest extends HierarchyViewTestBase {
public void testThroughAnonymousCalledByOther() throws Exception {
doJavaCallerTypeHierarchyTest("x.AcmClientImpl", "returnSomething", "X.java");
}
public void testWildcards() throws Exception {
doJavaCallerTypeHierarchyTest("p.BoardImpl", "getCount", "A.java");
}
}