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 128 129 130 131 132 133 134 135 136 137 | 18x 6x 6x 1x 7x 6x 7x 6x 7x 6x 6x 1x 1x 1x 1x 1x 6x 6x 6x 6x 6x | import { scanFiles, readFileContent } from '@aiready/core';
import type {
ContextAnalysisResult,
ContextAnalyzerOptions,
FileClassification,
} from './types';
import { calculateEnhancedCohesion } from './metrics';
import { analyzeIssues } from './issue-analyzer';
import {
buildDependencyGraph,
detectCircularDependencies,
} from './graph-builder';
import { detectModuleClusters } from './cluster-detector';
import { mapNodeToResult } from './mapper';
/**
* Calculate cohesion score (how related are exports in a file).
* Legacy wrapper for backward compatibility with exact test expectations.
*
* @param exports - List of exported symbols
* @param filePath - Path to the file being analyzed
* @param options - Additional options for cohesion calculation
* @returns Cohesion score between 0 and 1
*/
export function calculateCohesion(
exports: any[],
filePath?: string,
options?: any
): number {
return calculateEnhancedCohesion(exports, filePath, options);
}
/**
* Performs deep context analysis of a project.
* Scans files, builds a dependency graph, calculates context budgets,
* and identifies structural issues like high fragmentation or depth.
*
* @param options - Analysis parameters including root directory and focus areas
* @returns Comprehensive analysis results with metrics and identified issues
*/
export async function analyzeContext(
options: ContextAnalyzerOptions
): Promise<ContextAnalysisResult[]> {
const {
maxDepth = 5,
maxContextBudget = 25000,
minCohesion = 0.6,
maxFragmentation = 0.5,
includeNodeModules = false,
...scanOptions
} = options;
const files = await scanFiles({
...scanOptions,
exclude:
includeNodeModules && scanOptions.exclude
? scanOptions.exclude.filter(
(pattern) => pattern !== '**/node_modules/**'
)
: scanOptions.exclude,
});
const pythonFiles = files.filter((f) => f.toLowerCase().endsWith('.py'));
const fileContents = await Promise.all(
files.map(async (file) => ({
file,
content: await readFileContent(file),
}))
);
const graph = await buildDependencyGraph(
fileContents.filter((f) => !f.file.toLowerCase().endsWith('.py'))
);
let pythonResults: ContextAnalysisResult[] = [];
if (pythonFiles.length > 0) {
const { analyzePythonContext } = await import('./analyzers/python-context');
const pythonMetrics = await analyzePythonContext(
pythonFiles,
scanOptions.rootDir || options.rootDir || '.'
);
pythonResults = pythonMetrics.map((metric) => {
const { severity, issues, recommendations, potentialSavings } =
analyzeIssues({
file: metric.file,
importDepth: metric.importDepth,
contextBudget: metric.contextBudget,
cohesionScore: metric.cohesion,
fragmentationScore: 0,
maxDepth,
maxContextBudget,
minCohesion,
maxFragmentation,
circularDeps: [],
});
return {
file: metric.file,
tokenCost: 0,
linesOfCode: 0,
importDepth: metric.importDepth,
dependencyCount: 0,
dependencyList: [],
circularDeps: [],
cohesionScore: metric.cohesion,
domains: [],
exportCount: 0,
contextBudget: metric.contextBudget,
fragmentationScore: 0,
relatedFiles: [],
fileClassification: 'unknown' as FileClassification,
severity,
issues,
recommendations,
potentialSavings,
};
});
}
const clusters = detectModuleClusters(graph);
const allCircularDeps = detectCircularDependencies(graph);
const results: ContextAnalysisResult[] = Array.from(graph.nodes.values()).map(
(node) =>
mapNodeToResult(node, graph, clusters, allCircularDeps, {
maxDepth,
maxContextBudget,
minCohesion,
maxFragmentation,
})
);
return [...results, ...pythonResults];
}
|