UNPKG

agentsqripts

Version:

Comprehensive static code analysis toolkit for identifying technical debt, security vulnerabilities, performance issues, and code quality problems

149 lines (131 loc) 5.65 kB
/** * @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'); 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 };