replaceOffsetRange method

TextDocumentChange replaceOffsetRange({
  1. required int startOffset,
  2. required int endOffset,
  3. List<String> replacement = const <String>[],
})

Implementation

TextDocumentChange replaceOffsetRange({
  required int startOffset,
  required int endOffset,
  List<String> replacement = const <String>[],
}) {
  final normalizedStart = startOffset.clamp(0, length);
  final normalizedEnd = endOffset.clamp(normalizedStart, length);
  final startPosition = positionForOffset(normalizedStart);
  final oldEndPosition = positionForOffset(normalizedEnd);
  if (matchesOffsetRange(
        startOffset: normalizedStart,
        graphemes: replacement,
      ) &&
      normalizedStart + replacement.length == normalizedEnd) {
    return TextDocumentChange(
      startOffset: normalizedStart,
      oldEndOffset: normalizedEnd,
      newEndOffset: normalizedEnd,
      startPosition: startPosition,
      oldEndPosition: oldEndPosition,
      newEndPosition: oldEndPosition,
    );
  }

  final replacementLines = _parseFlatGraphemes(replacement);
  final prefixGraphemes = startPosition.column <= 0
      ? const <String>[]
      : _storage.graphemesInLineRange(
          startPosition.line,
          startColumn: 0,
          endColumn: startPosition.column,
        );
  final endLineLength = lineLength(oldEndPosition.line);
  final suffixGraphemes = oldEndPosition.column >= endLineLength
      ? const <String>[]
      : _storage.graphemesInLineRange(
          oldEndPosition.line,
          startColumn: oldEndPosition.column,
          endColumn: endLineLength,
        );
  final mergedLines = List<List<String>>.generate(
    replacementLines.length,
    (index) => List<String>.from(replacementLines[index], growable: true),
    growable: true,
  );
  mergedLines.first.insertAll(0, prefixGraphemes);
  mergedLines.last.addAll(suffixGraphemes);

  final replacementLineTexts = replacementLines
      .map((line) => line.join())
      .toList(growable: false);
  final replacementLineLengths = replacementLines
      .map((line) => line.length)
      .toList(growable: false);
  final replacementStorage = _pieceBackedReplacementStorageFromLineTexts(
    storage: _storage,
    startPosition: startPosition,
    oldEndPosition: oldEndPosition,
    replacementLineTexts: replacementLineTexts,
    replacementLineLengths: replacementLineLengths,
  );
  final nextReplacementStorage =
      replacementStorage ??
      _storageBuilder.fromParsedLines(
        mergedLines,
        revision: 0,
        seedLineGraphemeCaches: false,
      );
  final nextSegments = <_TextDocumentStorageSegment>[
    if (startPosition.line > 0) _storage.slice(0, startPosition.line),
    nextReplacementStorage.slice(0, nextReplacementStorage.lineCount),
    if (oldEndPosition.line + 1 < _storage.lineCount)
      _storage.slice(oldEndPosition.line + 1, _storage.lineCount),
  ];
  _storage = _storageBuilder.fromSegments(
    nextSegments,
    revision: _storage.revision + 1,
  );

  final newEndOffset = normalizedStart + replacement.length;
  return TextDocumentChange(
    startOffset: normalizedStart,
    oldEndOffset: normalizedEnd,
    newEndOffset: newEndOffset,
    startPosition: startPosition,
    oldEndPosition: oldEndPosition,
    newEndPosition: positionForOffset(newEndOffset),
  );
}