@Override
    protected void applyFix(@NotNull Project project, @NotNull PsiElement startElement, @NotNull ModPsiUpdater updater) {
      // smart psi pointer lost correct catch section when multiple catch sections were collapsed in batch mode,
      // so we need to re-calculate everything based on what exists at this point
      final PsiCatchSection catchSection = (PsiCatchSection)startElement;
      final PsiTryStatement tryStatement = (PsiTryStatement)catchSection.getParent();
      final CatchSectionWrapper[] sections = CatchSectionWrapper.createWrappers(tryStatement);
      if (sections == null) return;

      int sectionIndex = getSectionIndex(sections, catchSection);
      if (sectionIndex < 0) return;

      CatchSectionWrapper duplicateSection = sections[sectionIndex];
      if (duplicateSection == null) return;

      final boolean[][] canSwap = collectCanSwap(sections);
      final CatchSectionIndices[] duplicatesIndices =
        getCatchSectionIndices(sections, canSwap, myEmpty ? CatchSectionWrapper::areEmpty : (s1, s2) -> CatchSectionWrapper.areDuplicates(
          s1, s2, myIgnoreBlocksWithDifferentComments));
      if (duplicatesIndices == null) return;

      final int collapseIntoIndex = duplicatesIndices[sectionIndex].myCollapseIntoIndex;
      if (collapseIntoIndex < 0) return;

      CatchSectionWrapper collapseIntoSection = sections[collapseIntoIndex];
      if (collapseIntoSection == null) return;

      final PsiTypeElement collapseIntoTypeElement = collapseIntoSection.myParameter.getTypeElement();
      if (collapseIntoTypeElement == null) return;

      final List<PsiType> parameterTypes = new ArrayList<>(collapseIntoSection.myTypes);
      parameterTypes.addAll(duplicateSection.myTypes);

      final List<PsiType> filteredTypes = PsiDisjunctionType.flattenAndRemoveDuplicates(parameterTypes);
      final PsiType disjunction = PsiDisjunctionType.createDisjunction(filteredTypes, tryStatement.getManager());
      List<PsiClassType> targetTypes = CatchSectionWrapper.getClassTypes(disjunction);
      //try to choose catch block, which has target exception types. It helps to preserve names of variables and comments
      if (targetTypes != null && targetTypes.equals(duplicateSection.myTypes)) {
        CatchSectionWrapper temp = collapseIntoSection;
        collapseIntoSection = duplicateSection;
        duplicateSection = temp;
      }
      final Set<String> survivingCommentTexts = new HashSet<>(collectCommentTexts(collapseIntoSection.myCatchSection));

      final PsiTypeElement newTypeElement = JavaPsiFacade.getElementFactory(project).createTypeElement(disjunction);

      final CommentTracker tracker = new CommentTracker();

      JavaCodeStyleManager.getInstance(project).shortenClassReferences(tracker.replace(collapseIntoTypeElement, newTypeElement));

      int insertBeforeIndex = duplicatesIndices[sectionIndex].myCanInsertBefore;
      if (collapseIntoIndex < insertBeforeIndex) {
        // We can't leave the merged 'catch' section at collapseIntoIndex because it conflicts with other caught exceptions
        final PsiCatchSection[] catchSections = tryStatement.getCatchSections();
        if (insertBeforeIndex < catchSections.length && catchSections[insertBeforeIndex] != null) {
          CatchSectionWrapper finalCollapseIntoSection = collapseIntoSection;
          CodeStyleManager.getInstance(tryStatement.getProject()).performActionWithFormatterDisabled((Runnable)() -> {
            PsiCatchSection sectionToMove = finalCollapseIntoSection.myCatchSection;
            PsiElement toCopy = null;
            if (sectionToMove.getNextSibling() instanceof PsiWhiteSpace whiteSpace) {
              toCopy = whiteSpace.copy();
            }
            PsiElement element = tryStatement.addBefore(finalCollapseIntoSection.myCatchSection, catchSections[insertBeforeIndex]);
            if (toCopy != null) {
              tryStatement.addAfter(toCopy, element);
            }
            if (sectionToMove.getNextSibling() instanceof PsiWhiteSpace psiWhiteSpace) {
              psiWhiteSpace.delete();
            }
            sectionToMove.delete();
          });
        }
      }

      PsiTreeUtil.processElements(duplicateSection.myCatchSection, element -> {
        if (element instanceof PsiComment) {
          final String text = getCommentText((PsiComment)element);
          if (text.isEmpty() || survivingCommentTexts.contains(text)) {
            tracker.markUnchanged(element);
          }
        }
        return true;
      });

      tracker.grabComments(duplicateSection.myCatchSection);
      tracker.insertCommentsBefore(duplicateSection.myCatchSection);
      CatchSectionWrapper finalDuplicateSection = duplicateSection;
      CodeStyleManager.getInstance(tryStatement.getProject()).performActionWithFormatterDisabled((Runnable)() -> {
        if (finalDuplicateSection.myCatchSection.getNextSibling() instanceof PsiWhiteSpace whiteSpace) {
          whiteSpace.delete();
        }
        finalDuplicateSection.myCatchSection.delete();
      });
    }
@Override
    protected void applyFix(@NotNull Project project, @NotNull PsiElement startElement, @NotNull ModPsiUpdater updater)