function applyDelta()

in src/powerquery-parser/parser/nodeIdMap/nodeIdMapUtils/idUtils.ts [130:220]


function applyDelta(
    nodeIdMapCollection: Collection,
    newIdByOldId: Map<number, number>,
    xorNodes: ReadonlyArray<TXorNode>,
    delta: CollectionDelta,
): void {
    const newIds: ReadonlySet<number> = new Set(newIdByOldId.values());
    const oldLeafIds: ReadonlySet<number> = new Set(nodeIdMapCollection.leafIds.values());

    for (const xorNode of xorNodes) {
        const oldId: number = xorNode.node.id;
        const newId: number = MapUtils.assertGet(newIdByOldId, oldId);

        // Update nodeIds for either Ast.TNode or ParseContext.Node,
        // both in the NodeIdMap.Collection and on the node itself.
        if (XorNodeUtils.isAstXor(xorNode)) {
            const mutableNode: TypeScriptUtils.StripReadonly<Ast.TNode> = xorNode.node;
            mutableNode.id = newId;
            nodeIdMapCollection.astNodeById.set(newId, mutableNode);

            if (!delta.astNodeById.has(oldId)) {
                nodeIdMapCollection.astNodeById.delete(oldId);
            }
        } else {
            const mutableNode: TypeScriptUtils.StripReadonly<ParseContext.TNode> = xorNode.node;
            mutableNode.id = newId;
            nodeIdMapCollection.contextNodeById.set(newId, mutableNode);

            if (!delta.contextNodeById.has(oldId)) {
                nodeIdMapCollection.contextNodeById.delete(oldId);
            }
        }

        // If the nodeId had any children then update the links.
        const maybeChildIds: ReadonlyArray<number> | undefined = delta.childIdsById.get(newId);

        if (maybeChildIds !== undefined) {
            nodeIdMapCollection.childIdsById.set(newId, maybeChildIds);

            if (!delta.parentIdById.has(oldId)) {
                MapUtils.assertDelete(nodeIdMapCollection.childIdsById, oldId);
            }
        } else {
            nodeIdMapCollection.childIdsById.delete(newId);
        }

        if (oldLeafIds.has(oldId)) {
            nodeIdMapCollection.leafIds.add(newId);
        }

        // Delete oldId if:
        //  * another iteration doesn't update its id to oldId
        //  * OR oldId wasn't a leafId to begin with.
        if (!newIds.has(oldId) || oldLeafIds.has(oldId)) {
            nodeIdMapCollection.leafIds.delete(oldId);
        }

        const idsForSpecificNodeKind: Set<number> = MapUtils.assertGet(
            nodeIdMapCollection.idsByNodeKind,
            xorNode.node.kind,
        );

        // We need the NodeKind to check if we should do a deletion.
        // It must either be something in the delta, or something untouched in the nodeIdMapCollection.
        const oldKind: Ast.NodeKind =
            delta.astNodeById.get(oldId)?.kind ||
            delta.contextNodeById.get(oldId)?.kind ||
            NodeIdMapUtils.assertGetXor(nodeIdMapCollection, oldId).node.kind;

        idsForSpecificNodeKind.add(newId);

        // Delete oldId if:
        //  * another iteration doesn't update its id to oldId
        //  * OR the old node's kind doesn't match this iterations kind
        if (!newIds.has(oldId) || xorNode.node.kind !== oldKind) {
            idsForSpecificNodeKind.delete(oldId);
        }

        const maybeParentId: number | undefined = delta.parentIdById.get(newId);

        if (maybeParentId !== undefined) {
            nodeIdMapCollection.parentIdById.set(newId, maybeParentId);

            if (!delta.parentIdById.has(oldId)) {
                MapUtils.assertDelete(nodeIdMapCollection.parentIdById, oldId);
            }
        } else {
            nodeIdMapCollection.parentIdById.delete(newId);
        }
    }
}