generatedSubtreeCompress function

GeneratedTreeSitterNode generatedSubtreeCompress(
  1. GeneratedTreeSitterNode self,
  2. int count, {
  3. Set<GeneratedTreeSitterNode> sharedNodes = const <GeneratedTreeSitterNode>{},
})

Immutable counterpart of Tree-sitter 0.25.10's ts_subtree_compress rotation.

Native mutates uniquely-owned nodes in place. Generated subtrees are immutable, so each mutation is represented by rebuilding exactly the nodes whose child arrays change. The promoted grandchild becomes the next tree to compress, and the saved ancestors are summarized while unwinding, matching the native stack order.

Implementation

GeneratedTreeSitterNode generatedSubtreeCompress(
  GeneratedTreeSitterNode self,
  int count, {
  Set<GeneratedTreeSitterNode> sharedNodes = const <GeneratedTreeSitterNode>{},
}) {
  if (count <= 0) return self;
  final ancestors = <GeneratedTreeSitterNode>[];
  var tree = self;
  final symbol = tree.symbol;

  for (var index = 0; index < count; index++) {
    if (sharedNodes.contains(tree) || tree.children.length < 2) break;
    final child = tree.children.first;
    if (sharedNodes.contains(child) ||
        child.children.length < 2 ||
        child.symbol != symbol) {
      break;
    }
    final grandchild = child.children.first;
    if (sharedNodes.contains(grandchild) ||
        grandchild.children.length < 2 ||
        grandchild.symbol != symbol) {
      break;
    }

    final rebuiltChild = child.summarizedWithChildren(<GeneratedTreeSitterNode>[
      grandchild.children.last,
      ...child.children.skip(1),
    ]);
    final promotedGrandchild = grandchild.summarizedWithChildren(
      <GeneratedTreeSitterNode>[
        ...grandchild.children.take(grandchild.children.length - 1),
        rebuiltChild,
      ],
    );
    final rebuiltTree = tree.summarizedWithChildren(<GeneratedTreeSitterNode>[
      promotedGrandchild,
      ...tree.children.skip(1),
    ]);
    ancestors.add(rebuiltTree);
    tree = promotedGrandchild;
  }

  var result = tree;
  for (var index = ancestors.length - 1; index >= 0; index--) {
    final ancestor = ancestors[index];
    result = ancestor.summarizedWithChildren(<GeneratedTreeSitterNode>[
      result,
      ...ancestor.children.skip(1),
    ]);
  }
  return result;
}