@ApiStatus.Internal
  public void recalculate(@NotNull List<? extends Segment> ranges) {
    if (myIsDirty) {
      return;
    }
    if (myVisibleAreaWidth <= 0) {
      myIsDirty = true;
      return;
    }

    ranges.sort((o1, o2) -> {
      int startDiff = o1.getStartOffset() - o2.getStartOffset();
      return startDiff == 0 ? o2.getEndOffset() - o1.getEndOffset() : startDiff;
    });
    final int[] lastRecalculatedOffset = {0};
    SoftWrapAwareDocumentParsingListenerAdapter listener = new SoftWrapAwareDocumentParsingListenerAdapter() {
      @Override
      public void onRecalculationEnd(@NotNull IncrementalCacheUpdateEvent event) {
        lastRecalculatedOffset[0] = event.getActualEndOffset();
      }
    };
    myListeners.add(listener);
    try {
      for (Segment range : ranges) {
        int lastOffset = lastRecalculatedOffset[0];
        if (range.getEndOffset() > lastOffset) {
          recalculateSoftWraps(new IncrementalCacheUpdateEvent(Math.max(range.getStartOffset(), lastOffset), range.getEndOffset(),
                                                               myEditor));
        }
      }
    }
    finally {
      myListeners.remove(listener);
    }

    onRecalculationEnd();
  }
@ApiStatus.Internal
  public void recalculate(@NotNull List<? extends Segment> ranges)