summarizedWithChildren method

GeneratedTreeSitterNode summarizedWithChildren(
  1. List<GeneratedTreeSitterNode> value
)

Rebuilds every child-derived field using ts_subtree_summarize_children's rules.

Parser reductions normally construct an already summarized node. This method is the faithful managed counterpart for the native cases that replace a child array and then explicitly summarize it.

Implementation

GeneratedTreeSitterNode summarizedWithChildren(
  List<GeneratedTreeSitterNode> value,
) {
  if (value.isEmpty) {
    return GeneratedTreeSitterNode(
      symbol: symbol,
      structuralSymbol: structuralSymbol,
      type: type,
      startByte: startByte,
      endByte: startByte,
      startPoint: startPoint,
      endPoint: startPoint,
      named: named,
      visible: visible,
      extra: extra,
      productionId: productionId,
      dynamicPrecedence: 0,
      missing: missing,
      missingNameIsNamed: missingNameIsNamed,
      recoveryRepeat: _recoveryRepeat,
      unexpectedCharacter: unexpectedCharacter,
      children: const <GeneratedTreeSitterNode>[],
      fields: fields,
      productionFields: productionFields,
      parseState: parseState,
      firstLeafSymbol: 0,
      firstLeafParseState: 0,
      paddingBytes: 0,
      paddingExtent: const TreeSitterTablePoint(0, 0),
      sizeBytes: 0,
      sizeExtent: const TreeSitterTablePoint(0, 0),
      lookaheadBytes: 0,
      hasChanges: hasChanges,
      fragileLeft: fragileLeft || isError,
      fragileRight: fragileRight || isError,
      dependsOnColumn: false,
      isKeyword: isKeyword,
      hasExternalTokens: false,
    );
  }
  final first = value.first;
  final last = value.last;
  var lookaheadEndByte = first.paddingBytes + first.sizeBytes;
  var accumulatedBytes = 0;
  var accumulatedExtent = const TreeSitterTablePoint(0, 0);
  var depends = false;
  for (var index = 0; index < value.length; index++) {
    final child = value[index];
    // Native checks the parent's accumulated size before adding this child.
    if (accumulatedExtent.row == 0 && child.dependsOnColumn) depends = true;
    final totalBytes = child.paddingBytes + child.sizeBytes;
    accumulatedBytes += totalBytes;
    accumulatedExtent = _addTablePoint(
      accumulatedExtent,
      _addTablePoint(child.paddingExtent, child.sizeExtent),
    );
    final childLookaheadEnd = accumulatedBytes + child.lookaheadBytes;
    if (childLookaheadEnd > lookaheadEndByte) {
      lookaheadEndByte = childLookaheadEnd;
    }
  }
  final sizeBytes = accumulatedBytes - first.paddingBytes;
  final sizeExtent = _subtractTablePoint(
    accumulatedExtent,
    first.paddingExtent,
  );
  return GeneratedTreeSitterNode(
    symbol: symbol,
    structuralSymbol: structuralSymbol,
    type: type,
    startByte: first.startByte,
    endByte: first.startByte + sizeBytes,
    startPoint: first.startPoint,
    endPoint: _addTablePoint(first.startPoint, sizeExtent),
    named: named,
    visible: visible,
    extra: extra,
    productionId: productionId,
    dynamicPrecedence: value.fold<int>(
      0,
      (total, child) => total + child.dynamicPrecedence,
    ),
    missing: missing,
    missingNameIsNamed: missingNameIsNamed,
    recoveryRepeat: _recoveryRepeat,
    unexpectedCharacter: unexpectedCharacter,
    children: List<GeneratedTreeSitterNode>.unmodifiable(value),
    fields: fields,
    productionFields: productionFields,
    parseState: value.any((child) => child.isError) ? 0 : parseState,
    firstLeafSymbol: first.firstLeafSymbol ?? first.symbol,
    firstLeafParseState: first.firstLeafParseState,
    paddingBytes: first.paddingBytes,
    paddingExtent: first.paddingExtent,
    sizeBytes: sizeBytes,
    sizeExtent: sizeExtent,
    lookaheadBytes: lookaheadEndByte - accumulatedBytes,
    hasChanges: hasChanges,
    fragileLeft: fragileLeft || isError || first.fragileLeft,
    fragileRight: fragileRight || isError || last.fragileRight,
    dependsOnColumn: depends,
    isKeyword: isKeyword,
    hasExternalTokens: value.any((child) => child.hasExternalTokens),
    externalScannerStateBefore: first.externalScannerStateBefore,
    externalScannerStateAfter: last.externalScannerStateAfter,
  );
}