in src/vs/editor/common/model/intervalTree.ts [945:1127]
function rbTreeDelete(T: IntervalTree, z: IntervalNode): void {
let x: IntervalNode;
let y: IntervalNode;
// RB-DELETE except we don't swap z and y in case c)
// i.e. we always delete what's pointed at by z.
if (z.left === SENTINEL) {
x = z.right;
y = z;
// x's delta is no longer influenced by z's delta
x.delta += z.delta;
if (x.delta < Constants.MIN_SAFE_DELTA || x.delta > Constants.MAX_SAFE_DELTA) {
T.requestNormalizeDelta = true;
}
x.start += z.delta;
x.end += z.delta;
} else if (z.right === SENTINEL) {
x = z.left;
y = z;
} else {
y = leftest(z.right);
x = y.right;
// y's delta is no longer influenced by z's delta,
// but we don't want to walk the entire right-hand-side subtree of x.
// we therefore maintain z's delta in y, and adjust only x
x.start += y.delta;
x.end += y.delta;
x.delta += y.delta;
if (x.delta < Constants.MIN_SAFE_DELTA || x.delta > Constants.MAX_SAFE_DELTA) {
T.requestNormalizeDelta = true;
}
y.start += z.delta;
y.end += z.delta;
y.delta = z.delta;
if (y.delta < Constants.MIN_SAFE_DELTA || y.delta > Constants.MAX_SAFE_DELTA) {
T.requestNormalizeDelta = true;
}
}
if (y === T.root) {
T.root = x;
setNodeColor(x, NodeColor.Black);
z.detach();
resetSentinel();
recomputeMaxEnd(x);
T.root.parent = SENTINEL;
return;
}
let yWasRed = (getNodeColor(y) === NodeColor.Red);
if (y === y.parent.left) {
y.parent.left = x;
} else {
y.parent.right = x;
}
if (y === z) {
x.parent = y.parent;
} else {
if (y.parent === z) {
x.parent = y;
} else {
x.parent = y.parent;
}
y.left = z.left;
y.right = z.right;
y.parent = z.parent;
setNodeColor(y, getNodeColor(z));
if (z === T.root) {
T.root = y;
} else {
if (z === z.parent.left) {
z.parent.left = y;
} else {
z.parent.right = y;
}
}
if (y.left !== SENTINEL) {
y.left.parent = y;
}
if (y.right !== SENTINEL) {
y.right.parent = y;
}
}
z.detach();
if (yWasRed) {
recomputeMaxEndWalkToRoot(x.parent);
if (y !== z) {
recomputeMaxEndWalkToRoot(y);
recomputeMaxEndWalkToRoot(y.parent);
}
resetSentinel();
return;
}
recomputeMaxEndWalkToRoot(x);
recomputeMaxEndWalkToRoot(x.parent);
if (y !== z) {
recomputeMaxEndWalkToRoot(y);
recomputeMaxEndWalkToRoot(y.parent);
}
// RB-DELETE-FIXUP
let w: IntervalNode;
while (x !== T.root && getNodeColor(x) === NodeColor.Black) {
if (x === x.parent.left) {
w = x.parent.right;
if (getNodeColor(w) === NodeColor.Red) {
setNodeColor(w, NodeColor.Black);
setNodeColor(x.parent, NodeColor.Red);
leftRotate(T, x.parent);
w = x.parent.right;
}
if (getNodeColor(w.left) === NodeColor.Black && getNodeColor(w.right) === NodeColor.Black) {
setNodeColor(w, NodeColor.Red);
x = x.parent;
} else {
if (getNodeColor(w.right) === NodeColor.Black) {
setNodeColor(w.left, NodeColor.Black);
setNodeColor(w, NodeColor.Red);
rightRotate(T, w);
w = x.parent.right;
}
setNodeColor(w, getNodeColor(x.parent));
setNodeColor(x.parent, NodeColor.Black);
setNodeColor(w.right, NodeColor.Black);
leftRotate(T, x.parent);
x = T.root;
}
} else {
w = x.parent.left;
if (getNodeColor(w) === NodeColor.Red) {
setNodeColor(w, NodeColor.Black);
setNodeColor(x.parent, NodeColor.Red);
rightRotate(T, x.parent);
w = x.parent.left;
}
if (getNodeColor(w.left) === NodeColor.Black && getNodeColor(w.right) === NodeColor.Black) {
setNodeColor(w, NodeColor.Red);
x = x.parent;
} else {
if (getNodeColor(w.left) === NodeColor.Black) {
setNodeColor(w.right, NodeColor.Black);
setNodeColor(w, NodeColor.Red);
leftRotate(T, w);
w = x.parent.left;
}
setNodeColor(w, getNodeColor(x.parent));
setNodeColor(x.parent, NodeColor.Black);
setNodeColor(w.left, NodeColor.Black);
rightRotate(T, x.parent);
x = T.root;
}
}
}
setNodeColor(x, NodeColor.Black);
resetSentinel();
}