agentsqripts
Version:
Comprehensive static code analysis toolkit for identifying technical debt, security vulnerabilities, performance issues, and code quality problems
144 lines (127 loc) • 5.63 kB
JavaScript
/**
* @file Project-wide refactoring opportunity analyzer for comprehensive code organization assessment
* @description Single responsibility: Coordinate export promotion analysis across entire projects
*
* This analyzer orchestrates comprehensive project-wide analysis to identify export promotion
* opportunities and refactoring potential across all files. It provides strategic guidance
* for improving code reusability, API design, and module organization by analyzing function
* usage patterns, utility potential, and cross-file dependencies at scale.
*
* Design rationale:
* - Project-wide analysis identifies systematic refactoring opportunities missed by file-level analysis
* - Concurrent processing enables efficient analysis of large codebases without performance issues
* - Index file analysis provides insights into existing barrel file patterns and optimization opportunities
* - Priority-based recommendations enable focused refactoring efforts on highest-impact changes
* - Comprehensive metrics support data-driven architectural decision making
*
* Analysis scope:
* - Function export potential across all project files
* - Utility function identification and cross-file usage patterns
* - Existing barrel file analysis and optimization opportunities
* - Refactoring opportunity prioritization and impact assessment
* - API design improvement recommendations based on usage patterns
*/
const path = require('path');
// Import from atomic modules
const { analyzeFileRefactoring } = require('./fileRefactoringAnalyzer');
const { findIndexFiles } = require('./indexFileFinder');
const { analyzeIndexFile } = require('./indexFileAnalyzer');
const { generateRefactoringRecommendations } = require('./refactoringRecommendationGenerator');
const { getAllFiles } = require('./getAllFilesScanner');
/**
* Analyze project for refactoring opportunities
* @param {string} projectPath - Project directory path
* @param {Object} options - Analysis options
* @returns {Object} Project analysis results
*/
async function analyzeProjectRefactoring(projectPath, options = {}) {
const {
extensions = ['.js', '.ts', '.jsx', '.tsx'],
includeNonUtility = false,
includeBarrelFiles = true
} = options;
const startTime = Date.now();
const sourceFiles = await getAllFiles(projectPath, extensions);
const results = [];
const indexAnalysis = [];
// Analyze all source files concurrently
const analyses = await Promise.all(
sourceFiles.map(file => analyzeFileRefactoring(file, options))
);
// Filter and add results in single pass
for (const analysis of analyses) {
if (!analysis.error && (includeNonUtility || analysis.isUtility)) {
results.push(analysis);
}
}
// Analyze existing index files
if (includeBarrelFiles) {
const allDirectories = new Set(sourceFiles.map(f => path.dirname(f)));
// Process index files in single pass
const indexFilePromises = [];
for (const dir of allDirectories) {
const indexFiles = await findIndexFiles(dir, options);
indexFilePromises.push(...indexFiles.map(indexFile => analyzeIndexFile(indexFile)));
}
const indexAnalyses = await Promise.all(indexFilePromises);
// Filter and add valid analyses
for (const analysis of indexAnalyses) {
if (!analysis.error) {
indexAnalysis.push(analysis);
}
}
}
// Calculate project summary
const totalFiles = results.length;
const filesWithOpportunities = results.filter(r => r.metrics.hasRefactoringOpportunities).length;
const totalOpportunities = results.reduce((sum, r) => sum + r.metrics.promotionOpportunityCount, 0);
const refactoringRate = totalFiles > 0 ? Math.round(((totalFiles - filesWithOpportunities) / totalFiles) * 100) : 100;
// Opportunity type breakdown
const opportunityBreakdown = {
export_promotion: 0,
barrel_file_creation: 0
};
// Optimized breakdown calculation with flatMap
const opportunityCount = { export_promotion: 0, barrel_file_creation: 0 };
const priorityCount = { HIGH: 0, MEDIUM: 0, LOW: 0 };
// Process opportunities efficiently using index-based iteration
for (let i = 0; i < results.length; i++) {
const r = results[i];
const opportunities = r.promotionOpportunities;
for (let j = 0; j < opportunities.length; j++) {
const opp = opportunities[j];
opportunityCount[opp.type] = (opportunityCount[opp.type] || 0) + 1;
priorityCount[opp.priority || 'LOW']++;
}
}
Object.assign(opportunityBreakdown, opportunityCount);
const priorityBreakdown = priorityCount;
// Utility file statistics
const utilityFiles = results.filter(r => r.isUtility);
const utilityStats = {
totalUtilityFiles: utilityFiles.length,
totalUnexportedItems: utilityFiles.reduce((sum, r) => sum + r.metrics.unexportedCount, 0),
totalExportedItems: utilityFiles.reduce((sum, r) => sum + r.metrics.exportedCount, 0)
};
const analysisTime = Date.now() - startTime;
return {
timestamp: new Date().toISOString(),
summary: {
totalFiles,
filesWithOpportunities,
totalOpportunities,
refactoringRate,
opportunityBreakdown,
priorityBreakdown,
utilityStats,
indexFilesFound: indexAnalysis.length
},
files: results.filter(r => r.metrics.hasRefactoringOpportunities), // Only return files with opportunities
indexFiles: indexAnalysis,
recommendations: generateRefactoringRecommendations(opportunityBreakdown, priorityBreakdown, utilityStats),
analysisTime
};
}
module.exports = {
analyzeProjectRefactoring
};