private void combineRegularBlocksWithInjected(@NotNull ASTNode injectionHost, @NotNull List<Block> result,
                                                @NotNull List<Block> withInjections, @NotNull List<Block> regularBlocks) {
    int i = 0;
    int j = 0;
    int injectionHostOffset = injectionHost.getStartOffset();
    // Since there are possible injections without formatter blocks (i.e. whitespace only block),
    // we need to detect such scenarios and correctly split as if there was an injection.
    List<TextRange> injectedRanges = new ArrayList<>(withInjections.size());
    Int2ObjectMap<Block> injectedBlocksMap = new Int2ObjectOpenHashMap<>();
    boolean lastInjected = true;
    int lastOffset = 0;
    for (Block block : withInjections) {
      TextRange range = block.getTextRange();
      if (block instanceof AnotherLanguageBlockWrapper) {
        injectedRanges.add(range);
        injectedBlocksMap.put(range.getStartOffset(), block);
        lastInjected = true;
      }
      else {
        if (!lastInjected) {
          // add range for empty injection
          int offset = range.getStartOffset();
          injectedRanges.add(new TextRange(lastOffset, offset));
        }
        lastOffset = range.getEndOffset();
        lastInjected = false;
      }
    }
    // Perform actual splitting
    int injectedRangesCount = injectedRanges.size();
    while (i < regularBlocks.size()) {
      Block reg = regularBlocks.get(i);
      if (j < injectedRangesCount) {
        TextRange injRange = injectedRanges.get(j);
        TextRange regRange = reg.getTextRange();
        if (regRange.getEndOffset() <= injRange.getStartOffset()) {
          // Regular block does not intersect with injected - add
          result.add(reg);
          i++;
        }
        else if (injRange.getStartOffset() <= regRange.getStartOffset()
                 && regRange.getEndOffset() <= injRange.getEndOffset()) {
          // Regular block completely within injected - skip
          i++;
        }
        else {
          if (regRange.getStartOffset() < injRange.getStartOffset()) {
            // Regular block ends within or after an injected - split
            ASTNode node = notNull(injectionHost.findLeafElementAt(injRange.getStartOffset() - 1 - injectionHostOffset), injectionHost);
            result.add(createSimpleChild(node, reg.getIndent(), reg.getWrap(), reg.getAlignment(), new TextRange(
              regRange.getStartOffset(), injRange.getStartOffset())));
            if (regRange.getEndOffset() <= injRange.getEndOffset()) {
              // Block ends within injected - move to the next block
              i++;
              continue;
            }
            // Case of a regular block spanning over multiple injected ones
          }
          // Add injected block to the result
          addIfNotNull(result, injectedBlocksMap.get(injRange.getStartOffset()));
          j++;
          if (regRange.getStartOffset() < injRange.getEndOffset()) {
            // we have a regular block starting within or before last added injected block - split
            int lastInjection = injRange.getEndOffset();
            while (j < injectedRangesCount) {
              // check if single block does not span over next injected block
              TextRange nextRange = injectedRanges.get(j);
              if (nextRange.getStartOffset() < regRange.getEndOffset()) {
                // out regular block ends within or after the next injected block - add a split if it's not empty
                if (lastInjection < nextRange.getStartOffset()) {
                  ASTNode node = notNull(injectionHost.findLeafElementAt(lastInjection - injectionHostOffset), injectionHost);
                  result.add(createSimpleChild(node, reg.getIndent(), null, reg.getAlignment(),
                                               new TextRange(lastInjection, nextRange.getStartOffset())));
                }
                lastInjection = nextRange.getEndOffset();
                if (lastInjection <= regRange.getEndOffset()) {
                  // Add current injected block and repeat if regular block ends after it
                  addIfNotNull(result, injectedBlocksMap.get(nextRange.getStartOffset()));
                  j++;
                  continue;
                }
              }
              break;
            }
            // We might have some leftover of regular block after last added injected one,
            // which does not end within or after the next injected block - add a split
            if (lastInjection < regRange.getEndOffset()) {
              ASTNode node = notNull(injectionHost.findLeafElementAt(lastInjection - injectionHostOffset), injectionHost);
              result.add(createSimpleChild(node, reg.getIndent(), null, reg.getAlignment(),
                                           new TextRange(lastInjection, regRange.getEndOffset())));
            }
            i++;
          }
        }
      }
      else {
        // No more injected blocks to process, just add the regular ones
        result.add(reg);
        i++;
      }
    }
    // Add any leftover injected blocks
    while (j < injectedRangesCount) {
      addIfNotNull(result, injectedBlocksMap.get(injectedRanges.get(j++).getStartOffset()));
    }
  }
private void combineRegularBlocksWithInjected(@NotNull ASTNode injectionHost, @NotNull List<Block> result,
                                                @NotNull List<Block> withInjections, @NotNull List<Block> regularBlocks)