goto implementations: use type parameter bounds to detect overriding methods (IDEA-165282)

This commit is contained in:
Anna.Kozlova
2016-12-09 15:42:52 +01:00
parent 491dbb86f2
commit 152eaa4337
2 changed files with 46 additions and 8 deletions
@@ -292,7 +292,8 @@ public class JavaTargetElementEvaluator extends TargetElementEvaluatorEx2 implem
}
else if (expression != null) {
psiClass = PsiUtil.resolveClassInType(expression.getType());
} else {
}
else {
if (element instanceof PsiClass) {
psiClass = (PsiClass)element;
final PsiElement resolve = ((PsiReferenceExpression)reference).advancedResolve(true).getElement();
@@ -306,15 +307,31 @@ public class JavaTargetElementEvaluator extends TargetElementEvaluatorEx2 implem
if (containingClass == null && psiClass == null) return PsiClass.EMPTY_ARRAY;
if (containingClass != null) {
PsiElementFindProcessor<PsiClass> processor1 = new PsiElementFindProcessor<>(containingClass);
while (psiClass != null) {
if (!processor1.process(psiClass) ||
!ClassInheritorsSearch.search(containingClass).forEach(new PsiElementFindProcessor<>(psiClass)) ||
!ClassInheritorsSearch.search(psiClass).forEach(processor1)) {
return new PsiClass[] {psiClass};
if (psiClass instanceof PsiTypeParameter) {
List<PsiClass> result = new ArrayList<>();
for (PsiClassType classType : psiClass.getExtendsListTypes()) {
ContainerUtil.addIfNotNull(result, getInheritor(containingClass, classType.resolve()));
}
psiClass = psiClass.getContainingClass();
return result.isEmpty() ? null : result.toArray(PsiClass.EMPTY_ARRAY);
}
else {
PsiClass aClass = getInheritor(containingClass, psiClass);
if (aClass != null) return new PsiClass[] {aClass};
}
}
return null;
}
private PsiClass getInheritor(PsiClass containingClass, PsiClass psiClass) {
PsiElementFindProcessor<PsiClass> processor1 = new PsiElementFindProcessor<>(containingClass);
while (psiClass != null) {
if (!processor1.process(psiClass) ||
!ClassInheritorsSearch.search(containingClass).forEach(new PsiElementFindProcessor<>(psiClass)) ||
!ClassInheritorsSearch.search(psiClass).forEach(processor1)) {
return psiClass;
}
psiClass = psiClass.getContainingClass();
}
return null;
}
@@ -249,6 +249,27 @@ public class GotoImplementationHandlerTest extends JavaCodeInsightFixtureTestCas
assertEquals("A", aClass.getName());
}
public void testMethodImplementationsOnTypeVariable() throws Exception {
PsiFile file = myFixture.addFileToProject("Foo.java", "interface I {}\n" +
"interface Im {\n" +
" void m();\n" +
"}\n" +
"class Im1 implements Im {\n" +
" public void m() {}\n" +
"}\n" +
"class Im2 implements Im {\n" +
" public void m() {}\n" +
"}\n" +
"class JavaClass<T extends I & Im> {\n" +
" void a(T t){\n" +
" t.<caret>m();\n" +
" }\n" +
"}");
myFixture.configureFromExistingVirtualFile(file.getVirtualFile());
PsiElement[] targets = getTargets(file);
assertSize(2, targets);
}
public void testStaticMethodReference() {
PsiFile file = myFixture.addFileToProject("Foo.java",
"class C {\n" +