Skip to content

Commit d1f9db9

Browse files
authored
refactor(rush-lib): remove redundant path array in _findWorkspaceCycle
1 parent df8ba76 commit d1f9db9

1 file changed

Lines changed: 17 additions & 11 deletions

File tree

libraries/rush-lib/src/logic/WorkspaceCycleDetector.ts

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -50,32 +50,39 @@ export function detectAndReportWorkspaceCycles(
5050
* Finds one cycle in the workspace dependency graph, or returns `undefined` if there are none.
5151
*
5252
* Uses depth-first search with a "currently visiting" set for O(V + E) detection.
53+
* The `visiting` set doubles as the ordered path: ES6 Sets preserve insertion order,
54+
* so iterating it from the cycle-start node yields the cycle without a separate array.
5355
*/
5456
export function _findWorkspaceCycle(
5557
projects: ReadonlyArray<RushConfigurationProject>
5658
): ReadonlyArray<string> | undefined {
5759
// Nodes that have been fully explored (no cycles reachable from them)
5860
const visited: Set<RushConfigurationProject> = new Set();
59-
// Nodes currently on the DFS recursion stack
61+
// Nodes currently on the DFS recursion stack, in insertion order
6062
const visiting: Set<RushConfigurationProject> = new Set();
61-
// The current DFS path (used to extract the cycle path when one is found)
62-
const path: RushConfigurationProject[] = [];
6363

6464
function dfs(node: RushConfigurationProject): ReadonlyArray<string> | undefined {
6565
if (visited.has(node)) {
6666
return undefined;
6767
}
6868
if (visiting.has(node)) {
69-
// We've found a back-edge — extract the cycle from the current path
70-
const cycleStartIndex: number = path.indexOf(node);
71-
return [
72-
...path.slice(cycleStartIndex).map((p) => p.packageName),
73-
node.packageName // append the closing node to make the cycle explicit
74-
];
69+
// Back-edge found — iterate `visiting` (insertion order) and collect from
70+
// the cycle-start node onward, then close the loop.
71+
const cycleNames: string[] = [];
72+
let found: boolean = false;
73+
for (const n of visiting) {
74+
if (n === node) {
75+
found = true;
76+
}
77+
if (found) {
78+
cycleNames.push(n.packageName);
79+
}
80+
}
81+
cycleNames.push(node.packageName); // close the cycle
82+
return cycleNames;
7583
}
7684

7785
visiting.add(node);
78-
path.push(node);
7986

8087
for (const dep of node.dependencyProjects) {
8188
const cycle: ReadonlyArray<string> | undefined = dfs(dep);
@@ -84,7 +91,6 @@ export function _findWorkspaceCycle(
8491
}
8592
}
8693

87-
path.pop();
8894
visiting.delete(node);
8995
visited.add(node);
9096
return undefined;

0 commit comments

Comments
 (0)