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);
}
}
}