All files / src/semantic consolidation.ts

85.71% Statements 18/21
94.44% Branches 17/18
60% Functions 3/5
100% Lines 16/16

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                                        6x 6x 8x 8x 8x 9x 5x 5x 4x 1x   4x 1x   4x 4x 3x               6x    
import type { DependencyGraph } from '../types';
 
/**
 * Identify candidates for module consolidation based on high co-usage or shared types.
 *
 * @param graph - The dependency graph.
 * @param coUsageMatrix - Matrix of frequently paired files.
 * @param typeGraph - Map of shared type references.
 * @param minCoUsage - Minimum co-usage count threshold.
 * @param minSharedTypes - Minimum shared types threshold.
 * @returns Array of consolidation candidates sorted by strength.
 */
export function findConsolidationCandidates(
  graph: DependencyGraph,
  coUsageMatrix: Map<string, Map<string, number>>,
  typeGraph: Map<string, Set<string>>,
  minCoUsage: number = 5,
  minSharedTypes: number = 2
): { files: string[]; reason: string; strength: number }[] {
  const candidates: { files: string[]; reason: string; strength: number }[] =
    [];
  for (const [fileA, coUsages] of coUsageMatrix) {
    const nodeA = graph.nodes.get(fileA);
    Iif (!nodeA) continue;
    for (const [fileB, count] of coUsages) {
      if (fileB <= fileA || count < minCoUsage) continue;
      const nodeB = graph.nodes.get(fileB);
      if (!nodeB) continue;
      const typesA = new Set(
        nodeA.exports.flatMap((e) => e.typeReferences || [])
      );
      const typesB = new Set(
        nodeB.exports.flatMap((e) => e.typeReferences || [])
      );
      const sharedTypes = Array.from(typesA).filter((t) => typesB.has(t));
      if (sharedTypes.length >= minSharedTypes || count >= minCoUsage * 2) {
        candidates.push({
          files: [fileA, fileB],
          reason: `High co-usage (${count}x)`,
          strength: count / 10,
        });
      }
    }
  }
  return candidates.sort((a, b) => b.strength - a.strength);
}