void (final PsiMethod method) { final PsiTypeElement returnType = method.getReturnTypeElement(); for (PsiReference call : ReferencesSearch.search(method)) { final PsiElement ref = call.getElement(); if (PsiTreeUtil.getParentOfType(ref, PsiDocComment.class) != null) continue; final PsiElement parent = ref.getParent(); addLink(parent, returnType); } final PsiReturnStatement[] returnStatements = PsiUtil.findReturnStatements(method); for (final PsiReturnStatement returnStatement : returnStatements) { final PsiExpression returnValue = returnStatement.getReturnValue(); if (returnValue != null) { addLink(returnType, returnValue); } } final PsiMethod[] superMethods = method.findSuperMethods(); final class Inner { public void linkInheritors(final PsiMethod[] methods) { for (final PsiMethod superMethod : methods) { final PsiTypeElement superType = superMethod.getReturnTypeElement(); if (superType == null) continue; addLink(superType, returnType); addLink(returnType, superType); } } } new Inner().linkInheritors(superMethods); // ??? In the theory this is non-efficient way: too many inheritors can be processed (and multiple times). // ??? But in real use it seems reasonably fast. If poor performance problems emerged, // ??? should be optimized PsiClass containingClass = method.getContainingClass(); final PsiClass[] subClasses = ClassInheritorsSearch.search(containingClass, false).toArray(PsiClass.EMPTY_ARRAY); for (int i1 = 0; i1 != subClasses.length; ++i1) { final PsiMethod[] mBSs = subClasses[i1].findMethodsBySignature(method, true); new Inner().linkInheritors(mBSs); } }