public static @NotNull Set<TextRange> getPlaceholderRanges(@NotNull String s,
                                                    @NotNull String prefix,
                                                    @NotNull String suffix,
                                                    boolean useFullTextRange,
                                                    boolean filterNestedRanges) {
    if (!s.contains(prefix)) {
      return emptySet();
    }

    Set<TextRange> ranges = new LinkedHashSet<>(2);
    Deque<Integer> prefixes = new ArrayDeque<>();

    int searchFrom = 0;
    while (searchFrom < s.length()) {
      int nextSuffix = s.indexOf(suffix, searchFrom);
      if (nextSuffix < 0) {
        break; // no more suffixes to create ranges
      }
      int nextPrefix = s.indexOf(prefix, searchFrom);

      if (prefixes.isEmpty()) {
        if (nextPrefix < 0) {
          break; // no more prefixes to match with suffix
        }
        prefixes.push(nextPrefix);
        searchFrom = nextPrefix + 1;
      }
      else if (nextPrefix < 0
               || nextSuffix <= nextPrefix
               || nextPrefix + prefix.length() > nextSuffix) { // support overlapping tokens
        // suffix first
        int prefixPairPos = prefixes.pop();

        int startOffset = prefixPairPos + (useFullTextRange ? 0 : prefix.length());
        int endOffset = useFullTextRange ? nextSuffix + suffix.length() : nextSuffix;

        ranges.add(TextRange.create(startOffset, endOffset));

        // remove overlapping prefix positions from stack
        while (!prefixes.isEmpty() && prefixes.peek() + prefix.length() > prefixPairPos) {
          prefixes.pop();
        }

        searchFrom = nextSuffix + suffix.length();
      }
      else {
        // prefix first
        prefixes.push(nextPrefix);
        searchFrom = nextPrefix + 1;
      }
    }

    return filterNestedRanges ? filterNested(ranges) : ranges;
  }
public static @NotNull Set<TextRange> getPlaceholderRanges(@NotNull String s,
                                                    @NotNull String prefix,
                                                    @NotNull String suffix,
                                                    boolean useFullTextRange,
                                                    boolean filterNestedRanges)