public static int getLastVisualLineColumnNumber(@NotNull Editor editor, final int line) {
    if (editor instanceof EditorImpl editorImpl) {
      int lineEndOffset = line >= editorImpl.getVisibleLineCount()
                          ? editor.getDocument().getTextLength() : new VisualLinesIterator(editorImpl, line).getVisualLineEndOffset();
      return editor.offsetToVisualPosition(lineEndOffset, true, true).column;
    }


    return ReadAction.compute(() -> {
      Document document = editor.getDocument();
      int lastLine = document.getLineCount() - 1;
      if (lastLine < 0) {
        return 0;
      }

      // Filter all lines that are not shown because of a collapsed folding region.
      VisualPosition visStart = new VisualPosition(line, 0);
      LogicalPosition logStart = editor.visualToLogicalPosition(visStart);
      int lastLogLine = logStart.line;
      while (lastLogLine < document.getLineCount() - 1) {
        logStart = new LogicalPosition(logStart.line + 1, logStart.column);
        VisualPosition tryVisible = editor.logicalToVisualPosition(logStart);
        if (tryVisible.line != visStart.line) break;
        lastLogLine = logStart.line;
      }

      int resultLogLine = Math.min(lastLogLine, lastLine);
      VisualPosition resVisStart = editor.offsetToVisualPosition(document.getLineStartOffset(resultLogLine));
      VisualPosition resVisEnd = editor.offsetToVisualPosition(document.getLineEndOffset(resultLogLine));

      // Target logical line is not soft wrap affected.
      if (resVisStart.line == resVisEnd.line) {
        return resVisEnd.column;
      }

      int visualLinesToSkip = line - resVisStart.line;
      List<? extends SoftWrap> softWraps = editor.getSoftWrapModel().getSoftWrapsForLine(resultLogLine);
      for (int i = 0; i < softWraps.size(); i++) {
        SoftWrap softWrap = softWraps.get(i);
        CharSequence text = document.getCharsSequence();
        if (visualLinesToSkip <= 0) {
          VisualPosition visual = editor.offsetToVisualPosition(softWrap.getStart() - 1);
          int result = visual.column;
          int x = editor.visualPositionToXY(visual).x;
          // We need to add the width of the next symbol because the current result column points to the last symbol before the soft wrap.
          return result + textWidthInColumns(editor, text, softWrap.getStart() - 1, softWrap.getStart(), x);
        }

        int softWrapLineFeeds = StringUtil.countNewLines(softWrap.getText());
        if (softWrapLineFeeds < visualLinesToSkip) {
          visualLinesToSkip -= softWrapLineFeeds;
          continue;
        }

        // Target visual column is located on the last visual line of the current soft wrap.
        if (softWrapLineFeeds == visualLinesToSkip) {
          if (i >= softWraps.size() - 1) {
            return resVisEnd.column;
          }
          // We need to find visual column for line feed of the next soft wrap.
          SoftWrap nextSoftWrap = softWraps.get(i + 1);
          VisualPosition visual = editor.offsetToVisualPosition(nextSoftWrap.getStart() - 1);
          int result = visual.column;
          int x = editor.visualPositionToXY(visual).x;

          /* We need to add symbol width because current column points to the last symbol before the next soft wrap; */
          result += textWidthInColumns(editor, text, nextSoftWrap.getStart() - 1, nextSoftWrap.getStart(), x);

          int lineFeedIndex = StringUtil.indexOf(nextSoftWrap.getText(), '\n');
          result += textWidthInColumns(editor, nextSoftWrap.getText(), 0, lineFeedIndex, 0);
          return result;
        }

        // Target visual column is the one before line feed introduced by the current soft wrap.
        int softWrapStartOffset = 0;
        int softWrapEndOffset = 0;
        int softWrapTextLength = softWrap.getText().length();
        while (visualLinesToSkip-- > 0) {
          softWrapStartOffset = softWrapEndOffset + 1;
          if (softWrapStartOffset >= softWrapTextLength) {
            assert false;
            return resVisEnd.column;
          }
          softWrapEndOffset = StringUtil.indexOf(softWrap.getText(), '\n', softWrapStartOffset, softWrapTextLength);
          if (softWrapEndOffset < 0) {
            assert false;
            return resVisEnd.column;
          }
        }
        VisualPosition visual = editor.offsetToVisualPosition(softWrap.getStart() - 1);
        int result = visual.column; // Column of the symbol just before the soft wrap
        int x = editor.visualPositionToXY(visual).x;

        // Target visual column is located on the last visual line of the current soft wrap.
        result += textWidthInColumns(editor, text, softWrap.getStart() - 1, softWrap.getStart(), x);
        result += calcColumnNumber(editor, softWrap.getText(), softWrapStartOffset, softWrapEndOffset);
        return result;
      }

      CharSequence editorInfo = "editor's class: " + editor.getClass()
                                + ", all soft wraps: " + editor.getSoftWrapModel().getSoftWrapsForRange(0, document.getTextLength())
                                + ", fold regions: " + Arrays.toString(editor.getFoldingModel().getAllFoldRegions());
      LOG.error("Can't calculate last visual column", new Throwable(), AttachmentFactory.createContext(String.format(
        "Target visual line: %d, mapped logical line: %d, visual lines range for the mapped logical line: [%s]-[%s], soft wraps for "
        + "the target logical line: %s. Editor info: %s",
        line, resultLogLine, resVisStart, resVisEnd, softWraps, editorInfo
      )));

      return resVisEnd.column;
    });
  }
public static int getLastVisualLineColumnNumber(@NotNull Editor editor, final int line)