private List<PsiType> computePreciseCatchTypes(final @Nullable PsiParameter parameter) {
    if (parameter == null) {
      return ContainerUtil.emptyList();
    }

    PsiType declaredType = parameter.getType();

    // When the thrown expression is an ... exception parameter Ej (parameter) of a catch clause Cj (this) ...
    if (PsiUtil.isAvailable(JavaFeature.MULTI_CATCH, parameter) && isCatchParameterEffectivelyFinal(parameter, getCatchBlock())) {
      PsiTryStatement statement = getTryStatement();
      // ... and the try block of the try statement which declares Cj (tryBlock) can throw T ...
      Collection<PsiClassType> thrownTypes = getThrownTypes(statement);
      if (thrownTypes.isEmpty()) return Collections.emptyList();
      // ... and for all exception parameters Ei declared by any catch clauses Ci, 1 <= i < j,
      //     declared to the left of Cj for the same try statement, T is not assignable to Ei ...
      final PsiParameter[] parameters = statement.getCatchBlockParameters();
      final int currentIdx = ArrayUtil.find(parameters, parameter);
      List<PsiType> uncaughtTypes = ContainerUtil.mapNotNull(thrownTypes, thrownType -> {
        for (int i = 0; i < currentIdx; i++) {
          final PsiType catchType = parameters[i].getType();
          if (catchType.isAssignableFrom(thrownType)) return null;
        }
        return thrownType;
      });
      if (uncaughtTypes.isEmpty()) return Collections.emptyList();  // unreachable catch section
      // ... and T is assignable to Ej ...
      if (declaredType instanceof PsiDisjunctionType) {
        return Collections.unmodifiableList(((PsiDisjunctionType)declaredType).getDisjunctions()
                                              .stream()
                                              .flatMap(disjunction -> computePreciseCatchTypes(disjunction, uncaughtTypes).stream())
                                              .collect(Collectors.toCollection(() -> new ArrayList<>())));
      }
      else {
        return computePreciseCatchTypes(declaredType, uncaughtTypes);
      }
    }

    return Collections.singletonList(declaredType);
  }
private List<PsiType> computePreciseCatchTypes(final @Nullable PsiParameter parameter)