From d542048b46e3a6b5130ee41a5bdf925cd1277617 Mon Sep 17 00:00:00 2001 From: Pavlo-Bohdan Ravliv Date: Thu, 21 Mar 2024 16:44:53 +0100 Subject: [PATCH 1/2] add the actual cycle to the build output --- src/default-rules/circular-dependencies/index.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/default-rules/circular-dependencies/index.ts b/src/default-rules/circular-dependencies/index.ts index 8d493fad..74fa3cb9 100644 --- a/src/default-rules/circular-dependencies/index.ts +++ b/src/default-rules/circular-dependencies/index.ts @@ -48,8 +48,14 @@ export const validateRegistries = (maybeRegistries: string | string[] | undefine export const createNodeName = (node: string, commonPrefix: string): string => node.substring(commonPrefix.length, node.length) || commonPrefix; -const createUserOutput = (commonPrefix: string, cycleGraph: graphlib.Graph): string => - `cyclic root folder: ${commonPrefix}${EOL}${dot.write(cycleGraph)}`; +const createUserOutput = ( + commonPrefix: string, + cycleGraph: graphlib.Graph, + cycle: string[], +): string => + `cyclic root folder: ${commonPrefix}${EOL}${dot.write(cycleGraph)}${EOL}Cycle:${cycle.join( + ' -> ', + )}`; const createMappedCycleMessage = (cycle: string[], mapping: Mapping, graph: graphlib.Graph) => { const cycleGraph = new graphlib.Graph(); @@ -77,7 +83,7 @@ const createMappedCycleMessage = (cycle: string[], mapping: Mapping, graph: grap ); }); - return createUserOutput(commonPrefix, cycleGraph); + return createUserOutput(commonPrefix, cycleGraph, cycle); }; const createCycleMessage = (cycle: string[], graph: graphlib.Graph) => From e2ddca8fc84b00e004ba32920d5f834cf346dd79 Mon Sep 17 00:00:00 2001 From: Pavlo-Bohdan Ravliv Date: Fri, 22 Mar 2024 09:47:40 +0100 Subject: [PATCH 2/2] add functionality to find shortest cycle --- .../circular-dependencies/index.ts | 32 ++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/src/default-rules/circular-dependencies/index.ts b/src/default-rules/circular-dependencies/index.ts index 74fa3cb9..4b45db46 100644 --- a/src/default-rules/circular-dependencies/index.ts +++ b/src/default-rules/circular-dependencies/index.ts @@ -57,6 +57,36 @@ const createUserOutput = ( ' -> ', )}`; +function findShortestCycle(graph: graphlib.Graph): string[] | null { + let shortestCycle: string[] | null = null; + function dfs(node: string, visited: string[], allNodes: string[]): void { + visited.push(node); + allNodes.push(node); + + const successors = graph.successors(node); + if (successors) { + for (const successor of successors) { + if (!visited.includes(successor)) { + dfs(successor, visited, allNodes); + } else if (allNodes[0] === successor) { + if (!shortestCycle || allNodes.length < shortestCycle.length) { + shortestCycle = [...allNodes]; + } + } + } + } + + visited.pop(); + allNodes.pop(); + } + + for (const node of graph.nodes()) { + dfs(node, [], []); + } + + return shortestCycle; +} + const createMappedCycleMessage = (cycle: string[], mapping: Mapping, graph: graphlib.Graph) => { const cycleGraph = new graphlib.Graph(); const commonPrefix = getCommonPrefix(cycle); @@ -83,7 +113,7 @@ const createMappedCycleMessage = (cycle: string[], mapping: Mapping, graph: grap ); }); - return createUserOutput(commonPrefix, cycleGraph, cycle); + return createUserOutput(commonPrefix, cycleGraph, findShortestCycle(cycleGraph) || []); }; const createCycleMessage = (cycle: string[], graph: graphlib.Graph) =>