UNPKG

adam-java-analytics

Version:

Java code analyzer for detecting package dependencies and circular references

70 lines (57 loc) 1.8 kB
import { Dependency, Package } from "./analyzer" /** * Detects circular dependencies in the project */ export function detectCircularDependencies(packages: Package[], dependencies: Dependency[]): string[][] { const graph: Record<string, string[]> = {} // Build adjacency list packages.forEach((pkg) => { graph[pkg.name] = [] }) dependencies.forEach((dep) => { if (graph[dep.source]) { graph[dep.source].push(dep.target) } }) const cycles: string[][] = [] const visited = new Set<string>() const recursionStack = new Set<string>() function dfs(node: string, path: string[] = []): void { if (recursionStack.has(node)) { // Found a cycle const cycleStart = path.indexOf(node) if (cycleStart !== -1) { const cycle = path.slice(cycleStart).concat(node) // Check if this cycle or its rotation is already in cycles const isNewCycle = !cycles.some((existingCycle) => { if (existingCycle.length !== cycle.length) return false // Check all possible rotations for (let i = 0; i < existingCycle.length; i++) { const rotated = [...existingCycle.slice(i), ...existingCycle.slice(0, i)] if (JSON.stringify(rotated) === JSON.stringify(cycle)) return true } return false }) if (isNewCycle) { cycles.push(cycle) } } return } if (visited.has(node)) return visited.add(node) recursionStack.add(node) path.push(node) for (const neighbor of graph[node] || []) { dfs(neighbor, [...path]) } recursionStack.delete(node) } // Run DFS from each node for (const node of Object.keys(graph)) { if (!visited.has(node)) { dfs(node) } } return cycles }