# All files / src/semantic co-usage.ts

51.51% Statements 17/33
31.57% Branches 6/19
33.33% Functions 1/3
51.85% Lines 14/27

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

    23x

    23x
    39x

    39x
    29x
    29x

    29x
    45x
    45x
    45x

    45x
    45x
    45x

    23x

     import type { DependencyGraph, CoUsageData } from '../types';

    /**
     * Build co-usage matrix: track which files are imported together frequently.
     *
     * @param graph - The dependency graph to analyze.
     * @returns Map of file path to nested map of related files and their co-occurrence counts.
     */
    export function buildCoUsageMatrix(
      graph: DependencyGraph
    ): Map<string, Map<string, number>> {
      const coUsageMatrix = new Map<string, Map<string, number>>();

      for (const [, node] of graph.nodes) {
        const imports = node.imports;

        for (let i = 0; i < imports.length; i++) {
          const fileA = imports[i];
          if (!coUsageMatrix.has(fileA)) coUsageMatrix.set(fileA, new Map());

          for (let j = i + 1; j < imports.length; j++) {
            const fileB = imports[j];
            const fileAUsage = coUsageMatrix.get(fileA)!;
            fileAUsage.set(fileB, (fileAUsage.get(fileB) || 0) + 1);

            Iif (!coUsageMatrix.has(fileB)) coUsageMatrix.set(fileB, new Map());
            const fileBUsage = coUsageMatrix.get(fileB)!;
            fileBUsage.set(fileA, (fileBUsage.get(fileA) || 0) + 1);
          }
        }
      }

      return coUsageMatrix;
    }

    /**
     * Find semantic clusters using frequently occurring co-usage patterns.
     *
     * @param coUsageMatrix - The co-usage matrix from buildCoUsageMatrix.
     * @param minCoUsage - Minimum co-usage count to consider a strong relationship (default: 3).
     * @returns Map of cluster representative files to their associated cluster members.
     */
    export function findSemanticClusters(
      coUsageMatrix: Map<string, Map<string, number>>,
      minCoUsage: number = 3
    ): Map<string, string[]> {
      const clusters = new Map<string, string[]>();
      const visited = new Set<string>();

      for (const [file, coUsages] of coUsageMatrix) {
        if (visited.has(file)) continue;

        const cluster: string[] = [file];
        visited.add(file);

        for (const [relatedFile, count] of coUsages) {
          if (count >= minCoUsage && !visited.has(relatedFile)) {
            cluster.push(relatedFile);
            visited.add(relatedFile);
          }
        }

        if (cluster.length > 1) clusters.set(file, cluster);
      }

      return clusters;
    }

    /**
     * Retrieve co-usage data for a specific file.
     *
     * @param file - The file path to look up.
     * @param coUsageMatrix - The global co-usage matrix.
     * @returns Formatted co-usage data object.
     */
    export function getCoUsageData(
      file: string,
      coUsageMatrix: Map<string, Map<string, number>>
    ): CoUsageData {
      return {
        file,
        coImportedWith: coUsageMatrix.get(file) || new Map(),
        sharedImporters: [],
      };
    }