ThreeState (PsiClass class1, PsiClass class2, boolean avoidExpensiveProcessing) { if (class1 instanceof PsiTypeParameter) { final PsiClass[] superClasses = class1.getSupers(); ThreeState result = ThreeState.YES; for (PsiClass superClass : superClasses) { ThreeState state = existsMutualSubclass(superClass, class2, avoidExpensiveProcessing); if (state != ThreeState.YES) { result = state; if (result == ThreeState.NO) { return result; } } } return result; } if (class2 instanceof PsiTypeParameter) { return existsMutualSubclass(class2, class1, avoidExpensiveProcessing); } if (CommonClassNames.JAVA_LANG_OBJECT.equals(class1.getQualifiedName())) { return ThreeState.YES; } if (CommonClassNames.JAVA_LANG_OBJECT.equals(class2.getQualifiedName())) { return ThreeState.YES; } if (class1.isInheritor(class2, true) || class2.isInheritor(class1, true) || Objects.equals(class1, class2)) { return ThreeState.YES; } final SearchScope scope = GlobalSearchScope.allScope(class1.getProject()); String class1Name = class1.getName(); String class2Name = class2.getName(); if (class1Name == null || class2Name == null) { // One of classes is anonymous? No subclass is possible return ThreeState.NO; } if (class1.hasModifierProperty(PsiModifier.FINAL) || class2.hasModifierProperty(PsiModifier.FINAL)) return ThreeState.NO; if (LambdaUtil.isFunctionalClass(class1) || class1Name.length() < class2Name.length() || (isJavaClass(class2) && !isJavaClass(class1))) { // Assume that it could be faster to search inheritors from non-functional interface or from class with a longer simple name // Also prefer searching inheritors from Java class over other JVM languages as Java is usually faster PsiClass tmp = class1; class1 = class2; class2 = tmp; } if (DeclarationSearchUtils.isTooExpensiveToSearch(class1, false)) { if (!DeclarationSearchUtils.isTooExpensiveToSearch(class2, false)) { PsiClass tmp = class1; class1 = class2; class2 = tmp; } else if (avoidExpensiveProcessing) { // class inheritor search is too expensive on common names return ThreeState.UNSURE; } } return doSearch(class1, class2, avoidExpensiveProcessing, scope); }