forIndexedTree static method 
    
    
    
  Implementation
  @visibleForTesting
static TreeDiff forIndexedTree(
    {required IndexedTreeNode oldTree, required IndexedTreeNode newTree}) {
  final localUpdates = calculateListDiff<IndexedTreeNode>(
    List.from(oldTree.children),
    List.from(newTree.children),
    equalityChecker: (n1, n2) => n1.key == n2.key,
    detectMoves: false,
  ).getUpdatesWithData();
  final nodesInserted = <TreeDiffNodeInsert>[];
  final nodesRemoved = <TreeDiffNodeRemove>[];
  for (final update in localUpdates) {
    update.when(
      insert: (pos, data) {
        nodesInserted.add(TreeDiffNodeInsert(position: pos, data: data));
      },
      remove: (pos, data) {
        nodesRemoved.add(TreeDiffNodeRemove(data: data, position: pos));
      },
      change: (_, __, ___) {},
      move: (_, __, ___) {},
    );
  }
  final oldTreeMap = <String, IndexedNode>{
    for (final node in oldTree.children) node.key: node
  };
  final newTreeMap = <String, IndexedNode>{
    for (final node in newTree.children) node.key: node
  };
  final nodesUnchanged = <(IndexedTreeNode, IndexedTreeNode)>[];
  final nodesUpdated = <TreeDiffNodeUpdate>[];
  for (final nodeKey
      in oldTreeMap.keys.toSet().intersection(newTreeMap.keys.toSet())) {
    if ((oldTreeMap[nodeKey] as IndexedTreeNode).data !=
        (newTreeMap[nodeKey] as IndexedTreeNode).data) {
      nodesUpdated.add(TreeDiffNodeUpdate(newTreeMap[nodeKey]!));
    }
    nodesUnchanged.add(
      (
        oldTreeMap[nodeKey]! as IndexedTreeNode,
        newTreeMap[nodeKey]! as IndexedTreeNode,
      ),
    );
  }
  return TreeDiff._(
    oldTree: oldTree,
    newTree: newTree,
    nodesInserted: nodesInserted,
    nodesRemoved: nodesRemoved,
    nodesUnchanged: nodesUnchanged,
    nodesUpdated: nodesUpdated,
  );
}