private static @NotNull Map<Surrounder, PsiElement[]> computeSurrounders(@NotNull Editor editor, @NotNull PsiFile file) {
    SelectionModel selectionModel = editor.getSelectionModel();
    boolean hasSelection = selectionModel.hasSelection();
    if (!hasSelection) {
      selectLogicalLineContents(editor);
    }
    int[] startOffsets = editor.getCaretModel().getAllCarets().stream()
      .mapToInt(Caret::getSelectionStart)
      .toArray();
    int[] endOffsets = editor.getCaretModel().getAllCarets().stream()
      .mapToInt(Caret::getSelectionEnd)
      .toArray();

    final Language baseLanguage = file.getViewProvider().getBaseLanguage();

    Language previousLanguage = null;
    for (int i = 0; i < startOffsets.length; ++i) {
      PsiElement element1 = file.findElementAt(startOffsets[i]);
      PsiElement element2 = file.findElementAt(endOffsets[i] - 1);

      if (element1 == null || element2 == null) return Map.of();

      TextRange textRange = new TextRange(startOffsets[i], endOffsets[i]);
      for (SurroundWithRangeAdjuster adjuster : SurroundWithRangeAdjuster.EP_NAME.getExtensionList()) {
        textRange = adjuster.adjustSurroundWithRange(file, textRange, hasSelection);
        if (textRange == null) return Map.of();
      }
      startOffsets[i] = textRange.getStartOffset();
      endOffsets[i] = textRange.getEndOffset();

      element1 = file.findElementAt(startOffsets[0]);
      assert element1 != null;

      final Language currentLanguage = element1.getParent().getLanguage();
      if (previousLanguage != null && !currentLanguage.equals(previousLanguage)) {
        return Map.of();
      }
      previousLanguage = currentLanguage;
    }
    assert previousLanguage != null;

    List<SurroundDescriptor> surroundDescriptors = new ArrayList<>(LanguageSurrounders.INSTANCE.allForLanguage(previousLanguage));
    if (previousLanguage != baseLanguage) surroundDescriptors.addAll(LanguageSurrounders.INSTANCE.allForLanguage(baseLanguage));
    surroundDescriptors.add(CustomFoldingSurroundDescriptor.INSTANCE);

    int exclusiveCount = 0;
    List<SurroundDescriptor> exclusiveSurroundDescriptors = new ArrayList<>();
    for (SurroundDescriptor sd : surroundDescriptors) {
      if (sd.isExclusive()) {
        exclusiveCount++;
        exclusiveSurroundDescriptors.add(sd);
      }
    }

    if (exclusiveCount > 0) {
      surroundDescriptors = exclusiveSurroundDescriptors;
    }

    Map<Surrounder, PsiElement[]> surrounders = new LinkedHashMap<>();
    for (SurroundDescriptor descriptor : surroundDescriptors) {
      final PsiElement[] elements = getElementsToSurround(descriptor, file, startOffsets, endOffsets);
      if (elements.length > 0) {
        for (PsiElement element : elements) {
          assert element != null : "descriptor " + descriptor + " returned null element";
          assert element.isValid() : descriptor;
        }
        for (Surrounder s : descriptor.getSurrounders()) {
          surrounders.put(s, elements);
        }
      }
    }
    return surrounders;
  }
private static @NotNull Map<Surrounder, PsiElement[]> computeSurrounders(@NotNull Editor editor, @NotNull PsiFile file)