# All files / src/utils dependency-graph-utils.ts

88.88% Statements 56/63
75.75% Branches 25/33
100% Functions 6/6
91.22% Lines 52/57

Press n or j to go to the next uncovered block, b, p or k for the previous block.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127

    17x

    16x
    16x

    6x
    6x

    6x
    6x
    6x

    6x

    19x

    19x
    19x

    19x
    19x

    5x
    5x
    5x
    5x

    5x

    8x
    8x
    8x

    12x
    1x
    1x
    1x

    1x

    11x

    10x
    10x

    10x
    10x
    10x
    4x

    10x

    8x
    10x
    8x

    8x

    1x
    1x
    1x

    1x

    1x

    1x
    1x

    1x
    1x
    1x

    1x

    1x
    1x

     /**
     * Shared dependency graph utilities used by context analyzers.
     */

    export function calculateImportDepthFromEdges(
      file: string,
      edges: Map<string, Set<string>>,
      visited = new Set<string>(),
      depth = 0
    ): number {
      if (visited.has(file)) return depth;

      const dependencies = edges.get(file);
      if (!dependencies || dependencies.size === 0) return depth;

      const nextVisited = new Set(visited);
      nextVisited.add(file);

      let maxDepth = depth;
      for (const dep of dependencies) {
        maxDepth = Math.max(
          maxDepth,
          calculateImportDepthFromEdges(dep, edges, nextVisited, depth + 1)
        );
      }

      return maxDepth;
    }

    export function getTransitiveDependenciesFromEdges(
      file: string,
      edges: Map<string, Set<string>>,
      visited = new Set<string>()
    ): string[] {
      Iif (visited.has(file)) return [];

      const nextVisited = new Set(visited);
      nextVisited.add(file);

      const dependencies = edges.get(file);
      if (!dependencies || dependencies.size === 0) return [];

      const allDeps: string[] = [];
      for (const dep of dependencies) {
        allDeps.push(dep);
        allDeps.push(
          ...getTransitiveDependenciesFromEdges(dep, edges, nextVisited)
        );
      }

      return [...new Set(allDeps)];
    }

    export function detectGraphCycles(edges: Map<string, Set<string>>): string[][] {
      const cycles: string[][] = [];
      const visited = new Set<string>();
      const recursionStack = new Set<string>();

      function dfs(file: string, path: string[]): void {
        if (recursionStack.has(file)) {
          const cycleStart = path.indexOf(file);
          Eif (cycleStart !== -1) {
            cycles.push([...path.slice(cycleStart), file]);
          }
          return;
        }

        if (visited.has(file)) return;

        visited.add(file);
        recursionStack.add(file);

        const dependencies = edges.get(file);
        Eif (dependencies) {
          for (const dep of dependencies) {
            dfs(dep, [...path, file]);
          }
        }

        recursionStack.delete(file);
      }

      for (const file of edges.keys()) {
        if (!visited.has(file)) {
          dfs(file, []);
        }
      }

      return cycles;
    }

    export function detectGraphCyclesFromFile(
      file: string,
      edges: Map<string, Set<string>>
    ): string[][] {
      const cycles: string[][] = [];
      const visited = new Set<string>();
      const recursionStack = new Set<string>();

      function dfs(current: string, path: string[]): void {
        Iif (recursionStack.has(current)) {
          const cycleStart = path.indexOf(current);
          if (cycleStart !== -1) {
            cycles.push([...path.slice(cycleStart), current]);
          }
          return;
        }

        Iif (visited.has(current)) return;

        visited.add(current);
        recursionStack.add(current);

        const dependencies = edges.get(current);
        Eif (dependencies) {
          for (const dep of dependencies) {
            dfs(dep, [...path, current]);
          }
        }

        recursionStack.delete(current);
      }

      dfs(file, []);
      return cycles;
    }