fix tsb cyclic dependency check

This commit is contained in:
Johannes
2025-06-09 14:37:05 +02:00
parent 5586bddae5
commit 6bb8066506
4 changed files with 88 additions and 101 deletions

View File

@@ -63,53 +63,42 @@ export namespace graph {
return this._nodes.get(data) ?? null;
}
findCycle(): T[] | undefined {
let result: T[] | undefined;
let foundStartNodes = false;
const checked = new Set<Node<T>>();
for (const [_start, value] of this._nodes) {
if (Object.values(value.incoming).length > 0) {
findCycles(allData: T[]): Map<T, T[]> {
const result = new Map<T, T[]>();
const checked = new Set<T>();
for (const data of allData) {
const node = this.lookup(data);
if (!node) {
continue;
}
const r = this._findCycle(node, checked, new Set()) ?? [];
result.set(node.data, r);
}
return result;
}
foundStartNodes = true;
private _findCycle(node: Node<T>, checked: Set<T>, seen: Set<T>): T[] | undefined {
const dfs = (node: Node<T>, visited: Set<Node<T>>) => {
if (checked.has(node.data)) {
return undefined;
}
if (checked.has(node)) {
return;
}
if (visited.has(node)) {
result = [...visited, node].map(n => n.data);
const idx = result.indexOf(node.data);
result = result.slice(idx);
return;
}
visited.add(node);
for (const child of Object.values(node.outgoing)) {
dfs(child, visited);
if (result) {
break;
}
}
visited.delete(node);
checked.add(node);
};
dfs(value, new Set());
let result: T[] | undefined;
for (const child of node.outgoing.values()) {
if (seen.has(child.data)) {
const seenArr = Array.from(seen);
const idx = seenArr.indexOf(child.data);
seenArr.push(child.data);
return idx > 0 ? seenArr.slice(idx) : seenArr;
}
seen.add(child.data);
result = this._findCycle(child, checked, seen);
seen.delete(child.data);
if (result) {
break;
}
}
if (!foundStartNodes) {
// everything is a cycle
return Array.from(this._nodes.keys());
}
checked.add(node.data);
return result;
}
}