boolean (PsiClass aClass, Set<PsiClass> visited) { if (!aClass.hasModifierProperty(PsiModifier.PRIVATE)) return true; if (aClass instanceof PsiCompiledElement) return true; // don't check library code if (!visited.add(aClass)) return true; // prevent infinite recursion on broken code class LocalInheritorVisitor extends JavaRecursiveElementWalkingVisitor { private final Set<PsiClass> subclasses = new HashSet<>(); @Override public void visitReferenceElement(@NotNull PsiJavaCodeReferenceElement reference) { final PsiElement parent = reference.getParent(); if (!(parent instanceof PsiReferenceList)) return; final PsiElement grandParent = parent.getParent(); if (!(grandParent instanceof PsiClass)) return; if (reference.isReferenceTo(aClass)) { subclasses.add((PsiClass)grandParent); } } @Override public void visitReferenceExpression(@NotNull PsiReferenceExpression expression) {} public boolean isExtended() { return !subclasses.isEmpty(); } } PsiClass context = PsiUtil.getTopLevelClass(aClass); if (context == null) return false; final LocalInheritorVisitor visitor = new LocalInheritorVisitor(); context.accept(visitor); return visitor.isExtended() && ContainerUtil.exists(visitor.subclasses, subclass -> mayHaveScopeWideningSubclass(subclass, visited)); }