private static List<PsiType> computePreciseCatchTypes(PsiType declaredType, List<PsiType> uncaughtTypes) {
    List<PsiType> types = new SmartList<>();
    for (PsiType type : uncaughtTypes) {
      if (type.isAssignableFrom(declaredType)) {
        types.add(declaredType);
      }
      else if (declaredType.isAssignableFrom(type) ||
          // JLS 11.2.3 "Exception Checking":
          // "It is a compile-time error if a catch clause can catch checked exception class E1 and it is not the case
          // that the try block corresponding to the catch clause can throw a checked exception class that is
          // a subclass or superclass of E1, unless E1 is Exception or a superclass of Exception."
          // So here unchecked exception can sneak through Exception or Throwable catch type only.
          ExceptionUtil.isGeneralExceptionType(declaredType) && type instanceof PsiClassType && ExceptionUtil.isUncheckedException((PsiClassType)type)) {
        types.add(type);
      }
    }
    // ... the throw statement throws precisely the set of exception types T.
    return types;
  }
private static List<PsiType> computePreciseCatchTypes(PsiType declaredType, List<PsiType> uncaughtTypes)