@NotNull
  private static List<TextRange> buildSegments(@NotNull CharSequence editorText,
                                               final int cursorOffset,
                                               @NotNull TextRange range,
                                               @NotNull BitSet charEscapeLocations,
                                               @NotNull BitSet compositeIndexes) {
    if (range.getLength() == 0) {
      return Collections.emptyList();
    }
    int hostTextOffset = range.getStartOffset();
    int hostTextEndOffset = range.getEndOffset();

    List<TextRange> segments = new ArrayList<>();
    int rangeStart = hostTextOffset;
    boolean segmentsFinished = false;
    int hardSegmentCount = 0;

    for (int i = hostTextOffset; i < hostTextEndOffset; i++) {
      if (compositeIndexes.get(i - hostTextOffset)) {
        continue;
      }
      char ch = editorText.charAt(i);
      if (!segmentsFinished) {
        if (ch == '/'
            || (ch == '\\' && !charEscapeLocations.get(i - hostTextOffset))
            //treat space as soft segment marker
            || (ch == ' ' && i <= cursorOffset)) {
          if (rangeStart < i) {
            if (editorText.charAt(i - 1) == ':') {
              segments.add(new TextRange(rangeStart, i - 1));
            }
            else {
              segments.add(new TextRange(rangeStart, i));
            }
            if (i > cursorOffset) {
              segmentsFinished = true;
            }
          }
          rangeStart = i + 1;
          if (ch != ' ') {
            hardSegmentCount++;
          }
        }
        // URLs - expand to content after '?' first, but count it as soft segment
        else if (ch == '?') {
          segments.add(new TextRange(rangeStart, i));
          if (i + 1 < hostTextEndOffset) {
            segments.add(new TextRange(i + 1, hostTextEndOffset));
          }
          segments.add(new TextRange(rangeStart, hostTextEndOffset));
          segmentsFinished = true;
        }
      }
      // In case of encountering XML tag begin/end return empty segments list
      if ((ch == '>' && i > hostTextOffset && editorText.charAt(i - 1) == '/')
          || (ch == '<' && i + 1 < hostTextEndOffset && editorText.charAt(i + 1) == '/')) {
        return Collections.emptyList();
      }
    }
    if (hardSegmentCount <= 0) {
      return Collections.emptyList();
    }
    if (!segmentsFinished && rangeStart < hostTextEndOffset) {
      segments.add(new TextRange(rangeStart, hostTextEndOffset));
    }
    return segments;
  }
@NotNull
  private static List<TextRange> buildSegments(@NotNull CharSequence editorText,
                                               final int cursorOffset,
                                               @NotNull TextRange range,
                                               @NotNull BitSet charEscapeLocations,
                                               @NotNull BitSet compositeIndexes)