static @NotNull List<LookupElement> create(@NotNull PsiElement position) {
    PsiElement parent = PsiTreeUtil.getParentOfType(position, false, PsiTryStatement.class);
    if (!(parent instanceof PsiTryStatement tryStatement)) {
      return List.of();
    }

    PsiCodeBlock block = tryStatement.getTryBlock();
    if (block == null) {
      return List.of();
    }
    Project project = tryStatement.getProject();

    PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
    PsiStatement[] statements = block.getStatements();

    PsiCatchSection[] sections = tryStatement.getCatchSections();
    Set<@NotNull PsiType> existedExceptionTypes = new HashSet<>();
    List<String> stringExceptions = new ArrayList<>();

    for (PsiCatchSection section : sections) {
      PsiType catchType = section.getCatchType();
      if(catchType != null) {
        existedExceptionTypes.add(catchType);
      }
    }

    //if block is big enough, analyze can take a lot of time, let's use hardcoded exception
    if (block.getTextLength() > MAX_LIMIT_SIZE || existedExceptionTypes.size() > MAX_LOOKUP_SIZE) {
      stringExceptions.addAll(getHardcodedExceptions(existedExceptionTypes));
    }
    else {
      DumbService.getInstance(project).withAlternativeResolveEnabled(() -> {
        List<PsiClassType> exceptionTypes = getUnhandledExceptionTypes(statements);
        if (exceptionTypes.size() <= MAX_LOOKUP_SIZE) {
          List<@NotNull PsiClass> existedExceptionClasses =
            ContainerUtil.mapNotNull(existedExceptionTypes, exist -> PsiUtil.resolveClassInClassTypeOnly(exist));
          for (PsiClassType exceptionType : exceptionTypes) {
            PsiClass thrownException = PsiUtil.resolveClassInClassTypeOnly(exceptionType);
            if (thrownException != null &&
                !ContainerUtil.or(existedExceptionClasses,
                                  existed ->
                                    InheritanceUtil.isInheritorOrSelf(thrownException, existed, true))) {
              String qualifiedName = thrownException.getQualifiedName();
              if (qualifiedName != null) {
                stringExceptions.add(qualifiedName);
              }
            }
          }
        }
      });

      if (stringExceptions.isEmpty() || stringExceptions.size() > MAX_LOOKUP_SIZE) {
        stringExceptions.addAll(getHardcodedExceptions(existedExceptionTypes));
      }
    }

    List<LookupElement> lookupElements = new ArrayList<>();

    for (String stringException : stringExceptions) {
      try {
        PsiClassType exceptionType = factory.createTypeByFQClassName(stringException, tryStatement.getResolveScope());
        String name =
          new VariableNameGenerator(tryStatement, VariableKind.PARAMETER).byName("e", "ex", "exc").generate(false);
        PsiCatchSection catchSection = factory.createCatchSection(exceptionType, name, tryStatement);
        String catchSectionText = catchSection.getText();
        lookupElements.add(new CatchLookupElement(catchSection, catchSectionText));
        if (lookupElements.size() >= MAX_LOOKUP_SIZE) {
          break;
        }
      }
      catch (IncorrectOperationException e) {
        return List.of();
      }
    }

    return lookupElements;
  }
static @NotNull List<LookupElement> create(@NotNull PsiElement position)