List<TextRange> (@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; }