public TextRanges union(@Nullable TextRange range) {
    if (range == null || range.isEmpty()) return this;
    int startIdx = Collections.binarySearch(myRanges, TextRange.from(range.getStartOffset(), 0), END_COMP);
    int endIdx = Collections.binarySearch(myRanges, TextRange.from(range.getEndOffset(), 0), START_COMP);

    if (startIdx == endIdx) {
      assert startIdx < 0;
      myRanges.add(-startIdx - 1, range);
      return this;
    }
    if (startIdx < 0) startIdx = -startIdx - 1;
    if (endIdx < 0) endIdx = -endIdx - 1;
    List<TextRange> covered = myRanges.subList(startIdx, endIdx);
    TextRange newRange = new TextRange(
      Math.min(range.getStartOffset(), covered.get(0).getStartOffset()),
      Math.max(range.getEndOffset(), covered.get(covered.size() - 1).getEndOffset())
    );
    covered.clear();
    covered.add(newRange);
    return this;
  }
public TextRanges union(@Nullable TextRange range)