Set<PsiClassType> (@NotNull PsiElement element, @Nullable PsiElement topElement, @Nullable Set<PsiClassType> foundExceptions, @NotNull Predicate<? super PsiCallExpression> callFilter) { Collection<PsiClassType> unhandledExceptions = null; if (element instanceof PsiCallExpression) { PsiCallExpression expression = (PsiCallExpression)element; unhandledExceptions = getUnhandledExceptions(expression, topElement, callFilter); } else if (element instanceof PsiTemplateExpression) { unhandledExceptions = getUnhandledProcessorExceptions((PsiTemplateExpression)element, topElement); } else if (element instanceof PsiMethodReferenceExpression) { PsiExpression qualifierExpression = ((PsiMethodReferenceExpression)element).getQualifierExpression(); return qualifierExpression != null ? collectUnhandledExceptions(qualifierExpression, topElement, null, callFilter) : null; } else if (element instanceof PsiLambdaExpression) { return null; } else if (element instanceof PsiThrowStatement) { PsiThrowStatement statement = (PsiThrowStatement)element; unhandledExceptions = getUnhandledExceptions(statement, topElement); } else if (element instanceof PsiCodeBlock && element.getParent() instanceof PsiMethod && ((PsiMethod)element.getParent()).isConstructor() && !firstStatementIsConstructorCall((PsiCodeBlock)element)) { // there is implicit parent constructor call final PsiMethod constructor = (PsiMethod)element.getParent(); final PsiClass aClass = constructor.getContainingClass(); final PsiClass superClass = aClass == null ? null : aClass.getSuperClass(); final PsiMethod[] superConstructors = superClass == null ? PsiMethod.EMPTY_ARRAY : superClass.getConstructors(); Set<PsiClassType> unhandled = new HashSet<>(); for (PsiMethod superConstructor : superConstructors) { if (!superConstructor.hasModifierProperty(PsiModifier.PRIVATE) && superConstructor.getParameterList().isEmpty()) { final PsiClassType[] exceptionTypes = superConstructor.getThrowsList().getReferencedTypes(); for (PsiClassType exceptionType : exceptionTypes) { if (!isUncheckedException(exceptionType) && getHandlePlace(element, exceptionType, topElement) == HandlePlace.UNHANDLED) { unhandled.add(exceptionType); } } break; } } // plus all exceptions thrown in instance class initializers if (aClass != null) { final PsiClassInitializer[] initializers = aClass.getInitializers(); final Set<PsiClassType> thrownByInitializer = new HashSet<>(); for (PsiClassInitializer initializer : initializers) { if (initializer.hasModifierProperty(PsiModifier.STATIC)) continue; thrownByInitializer.clear(); collectUnhandledExceptions(initializer.getBody(), initializer, thrownByInitializer, callFilter); for (PsiClassType thrown : thrownByInitializer) { if (getHandlePlace(constructor.getBody(), thrown, topElement) == HandlePlace.UNHANDLED) { unhandled.add(thrown); } } } } unhandledExceptions = unhandled; } else if (element instanceof PsiResourceListElement) { final List<PsiClassType> unhandled = getUnhandledCloserExceptions((PsiResourceListElement)element, topElement); if (!unhandled.isEmpty()) { unhandledExceptions = new ArrayList<>(unhandled); } } if (unhandledExceptions != null) { if (foundExceptions == null) { foundExceptions = new HashSet<>(); } foundExceptions.addAll(unhandledExceptions); } for (PsiElement child = element.getFirstChild(); child != null; child = child.getNextSibling()) { Set<PsiClassType> foundInChild = collectUnhandledExceptions(child, topElement, foundExceptions, callFilter); if (foundExceptions == null) { foundExceptions = foundInChild; } else if (foundInChild != null) { foundExceptions.addAll(foundInChild); } } return foundExceptions; }