agentsqripts
Version:
Comprehensive static code analysis toolkit for identifying technical debt, security vulnerabilities, performance issues, and code quality problems
150 lines (132 loc) • 5.7 kB
JavaScript
/**
* @file Code complexity analysis orchestrator for maintainability assessment
* @description Single responsibility: Coordinate comprehensive complexity and technical debt analysis
*
* This main interface orchestrates multiple complexity metrics including cyclomatic complexity,
* maintainability index, and technical debt indicators. It provides actionable recommendations
* for improving code quality and reducing maintenance burden across JavaScript codebases.
*
* Design rationale:
* - Multi-metric approach provides comprehensive complexity assessment
* - Atomic module architecture enables focused testing and maintenance
* - Recommendation system connects metrics to actionable improvements
* - Error handling with qerrors provides detailed failure diagnostics
*
* @requires fs - File system operations
* @requires qerrors - Error logging
*/
const fs = require('fs');
const { promises: fsPromises } = require('fs');
// Removed qerrors dependency for qtests compatibility
// const qerrors = require('qerrors');
// Import directly from atomic modules
const { calculateCyclomaticComplexity } = require('./cyclomaticCalculator');
const { calculateMaintainabilityIndex } = require('./maintainabilityCalculator');
const { identifyComplexityIssues } = require('./complexityIssueDetector');
// Note: Technical debt analysis now in separate atomic module
/**
* Generate prioritized recommendations based on complexity analysis results
*
* Technical function: Transforms complexity metrics into actionable improvement suggestions
*
* Implementation rationale:
* - Threshold-based recommendations provide clear action triggers
* - Priority levels help teams focus on highest-impact improvements
* - Specific action items make recommendations immediately implementable
* - Positive reinforcement encourages maintaining good practices
*
* Recommendation strategy:
* - High complexity triggers immediate refactoring recommendations
* - Low maintainability suggests structural improvements
* - Multiple issues indicate systematic problems requiring broader attention
* - Good quality recognition reinforces positive patterns
*
* @param {Object} analysis - Analysis results
* @returns {Array} Array of recommendations
*/
function generateFileRecommendations(analysis) {
const recommendations = [];
if (analysis.complexity === 'HIGH') {
recommendations.push({
priority: 'HIGH',
title: 'High File Complexity',
description: 'This file has high complexity that may impact maintainability',
action: 'Focus on refactoring the most complex functions and reducing nesting'
});
}
if (analysis.maintainabilityIndex < 50) {
recommendations.push({
priority: 'MEDIUM',
title: 'Low Maintainability',
description: 'Low maintainability index indicates potential technical debt',
action: 'Consider breaking down large functions and improving code structure'
});
}
if (analysis.issues.length > 5) {
recommendations.push({
priority: 'MEDIUM',
title: 'Multiple Complexity Issues',
description: `Found ${analysis.issues.length} complexity issues in this file`,
action: 'Address the most critical issues first, focusing on deep nesting and long functions'
});
}
if (analysis.complexity === 'LOW' && analysis.maintainabilityIndex > 80) {
recommendations.push({
priority: 'LOW',
title: 'Good Code Quality',
description: 'This file maintains good complexity and maintainability standards',
action: 'Continue following current coding practices'
});
}
return recommendations;
}
/**
* Analyzes code complexity using various metrics
* @param {string} filePath - Path to the file to analyze
* @param {Object} options - Analysis options
* @returns {Object} Complexity analysis results
* @throws {Error} When file cannot be read or analyzed
*/
async function analyzeCodeComplexity(filePath, options = {}) {
try {
const content = await fsPromises.readFile(filePath, 'utf8');
const lines = content.split('\n');
const linesOfCode = lines.filter(line => line.trim() && !line.trim().startsWith('//')).length;
const cyclomaticComplexity = calculateCyclomaticComplexity(content);
const functionCount = (content.match(/function\s+\w+|const\s+\w+\s*=.*=>/g) || []).length;
const analysis = {
file: filePath,
metrics: {
linesOfCode,
cyclomaticComplexity,
functionCount,
classCount: (content.match(/class\s+\w+/g) || []).length
},
issues: [],
maintainabilityIndex: 0,
complexity: 'LOW'
};
analysis.maintainabilityIndex = calculateMaintainabilityIndex(
analysis.metrics.linesOfCode,
analysis.metrics.cyclomaticComplexity
);
analysis.complexity = analysis.metrics.cyclomaticComplexity > 20 ? 'HIGH' :
analysis.metrics.cyclomaticComplexity > 10 ? 'MEDIUM' : 'LOW';
analysis.issues = identifyComplexityIssues(content, analysis.metrics);
// Generate file-level recommendations
analysis.recommendations = generateFileRecommendations(analysis);
return analysis;
} catch (error) {
qerrors.default(error, 'analyzeCodeComplexity failed', { filePath, options });
throw error;
}
}
// Import additional functions for CLI compatibility
const { analyzeProjectComplexity } = require('./projectComplexityAnalyzer');
const { analyzeTechnicalDebt } = require('./technicalDebtAnalyzer');
// Export main function (following SRP - single responsibility)
module.exports = {
analyzeCodeComplexity,
analyzeProjectComplexity,
analyzeTechnicalDebt
};