generatedChangedRanges function

List<GeneratedTreeSitterChangedRange> generatedChangedRanges(
  1. GeneratedTreeSitterTree oldTree,
  2. GeneratedTreeSitterNode newRoot, {
  3. List<TreeSitterTableRange> newIncludedRanges = const [],
  4. int? newRootTotalEndByte,
  5. TreeSitterTablePoint? newRootTotalEndPoint,
  6. GeneratedChangedRangeTrace? trace,
})

Compares an edited old generated tree with a newly parsed tree and returns the minimal structurally changed generated-node ranges.

Implementation

List<GeneratedTreeSitterChangedRange> generatedChangedRanges(
  GeneratedTreeSitterTree oldTree,
  GeneratedTreeSitterNode newRoot, {
  List<TreeSitterTableRange> newIncludedRanges = const [],
  int? newRootTotalEndByte,
  TreeSitterTablePoint? newRootTotalEndPoint,
  GeneratedChangedRangeTrace? trace,
}) {
  final includedRangeDifferences = generatedIncludedRangeDifferences(
    oldTree.includedRanges,
    newIncludedRanges,
    trace: trace,
  );
  final results = <GeneratedTreeSitterChangedRange>[];
  final oldIterator = _ChangedRangeIterator.old(oldTree, trace);
  final newIterator = _ChangedRangeIterator.fresh(
    newRoot,
    oldTree.language,
    trace,
    rootTotalEndByte: newRootTotalEndByte,
    rootTotalEndPoint: newRootTotalEndPoint,
  );
  var includedRangeDifferenceIndex = 0;
  var position = oldIterator.startPosition();
  var nextPosition = newIterator.startPosition();
  if (position.byte < nextPosition.byte) {
    generatedRangeArrayAdd(results, position, nextPosition, trace: trace);
    position = nextPosition;
  } else if (position.byte > nextPosition.byte) {
    generatedRangeArrayAdd(results, nextPosition, position, trace: trace);
    nextPosition = position;
  }

  do {
    var comparison = oldIterator.compare(newIterator);
    if (comparison == _IteratorComparison.matches &&
        generatedRangeArrayIntersects(
          includedRangeDifferences,
          includedRangeDifferenceIndex,
          position.byte,
          oldIterator.endPosition().byte,
          trace: trace,
        )) {
      comparison = _IteratorComparison.mayDiffer;
    }

    var isChanged = false;
    switch (comparison) {
      case _IteratorComparison.matches:
        nextPosition = oldIterator.endPosition();
      case _IteratorComparison.mayDiffer:
        if (oldIterator.descend(position.byte)) {
          if (!newIterator.descend(position.byte)) {
            isChanged = true;
            nextPosition = oldIterator.endPosition();
          }
        } else if (newIterator.descend(position.byte)) {
          isChanged = true;
          nextPosition = newIterator.endPosition();
        } else {
          nextPosition = _minimumLength(
            oldIterator.endPosition(),
            newIterator.endPosition(),
          );
        }
      case _IteratorComparison.differs:
        isChanged = true;
        nextPosition = _minimumLength(
          oldIterator.endPosition(),
          newIterator.endPosition(),
        );
    }

    while (!oldIterator.done &&
        oldIterator.endPosition().byte <= nextPosition.byte) {
      oldIterator.advance();
    }
    while (!newIterator.done &&
        newIterator.endPosition().byte <= nextPosition.byte) {
      newIterator.advance();
    }
    while (oldIterator.visibleDepth > newIterator.visibleDepth) {
      oldIterator.ascend();
    }
    while (newIterator.visibleDepth > oldIterator.visibleDepth) {
      newIterator.ascend();
    }

    if (isChanged) {
      generatedRangeArrayAdd(results, position, nextPosition, trace: trace);
    }
    position = nextPosition;
    while (includedRangeDifferenceIndex < includedRangeDifferences.length) {
      if (includedRangeDifferences[includedRangeDifferenceIndex].endByte <=
          position.byte) {
        includedRangeDifferenceIndex++;
      } else {
        break;
      }
    }
  } while (!oldIterator.done && !newIterator.done);

  final oldSize = oldIterator.rootEnd;
  final newSize = newIterator.rootEnd;
  if (oldSize.byte < newSize.byte) {
    generatedRangeArrayAdd(results, oldSize, newSize, trace: trace);
  } else if (newSize.byte < oldSize.byte) {
    generatedRangeArrayAdd(results, newSize, oldSize, trace: trace);
  }
  trace?.record('ts_subtree_get_changed_ranges', <Object?>[
    for (final range in results) (range.startByte, range.endByte),
  ]);
  return List.unmodifiable(results);
}