UNPKG

agentsqripts

Version:

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

121 lines (102 loc) 4.52 kB
/** * @file Analyze entire project for WET code using improved approach * @description Single responsibility: Orchestrate project-wide WET code analysis */ const fs = require('fs'); const path = require('path'); const { fsPromises } = require('../../fileSystemUtils'); const qerrors = require('qerrors'); const { extractSemanticBlocks } = require('../../ast/astBlockExtractor'); const { analyzeFileContext } = require('../../ast/contextAnalyzer'); const { generateRefactoringRecommendations } = require('../../ast/refactoringRecommendationEngine'); const { getDryGrade, getWetGrade } = require('../../gradeCalculator'); const { getAllFiles, pathExists } = require('../../fileSystemUtils'); const { VALID_EXTENSIONS } = require('../../wetCodeConfig'); const findSemanticDuplicatesOptimized = require('./findSemanticDuplicatesOptimized'); const calculateProjectMetrics = require('../metrics/calculateProjectMetrics'); const identifyTopOffenders = require('../recommendations/identifyTopOffenders'); /** * Analyze entire project for WET code using improved approach * @param {string} projectPath - Root path of the project * @param {Object} options - Analysis options * @returns {Promise<Object>} Project-wide analysis results */ async function analyzeProjectWetCodeImproved(projectPath, options = {}) { try { console.log('🚀 Starting improved WET code analysis...'); const startTime = Date.now(); // Get all relevant files const extensions = options.extensions || VALID_EXTENSIONS; const files = await getAllFiles(projectPath, extensions, options.excludePatterns); console.log(`📁 Found ${files.length} files to analyze`); // Extract all blocks from all files with progress const allBlocks = []; const fileContexts = {}; const fileResults = []; for (let i = 0; i < files.length; i++) { const file = files[i]; // Show progress for large projects if (i % 50 === 0 && i > 0) { console.log(` Processing file ${i}/${files.length}...`); } try { const content = await fsPromises.readFile(file, 'utf8'); const context = analyzeFileContext(file, content); fileContexts[file] = context; if (!context.rules.skipAnalysis) { const blocks = extractSemanticBlocks(content, file); const relevantBlocks = blocks.filter(block => block.lineCount >= context.rules.minLines && block.complexity >= context.rules.minComplexity ); allBlocks.push(...relevantBlocks); fileResults.push({ file, blocks: relevantBlocks.length, context }); } } catch (error) { console.warn(` Warning: Could not analyze ${file}: ${error.message}`); } } console.log(`📊 Extracted ${allBlocks.length} semantic blocks`); // Find cross-file duplicates using optimized algorithm console.log('🔍 Finding semantic duplicates...'); const duplicateGroups = findSemanticDuplicatesOptimized(allBlocks, fileContexts); console.log(`✨ Found ${duplicateGroups.length} duplicate groups`); // Generate refactoring recommendations console.log('💡 Generating refactoring recommendations...'); const hasLibDirectory = await pathExists(path.join(projectPath, 'lib')); const recommendations = generateRefactoringRecommendations(duplicateGroups, { projectPath, hasLibDirectory }); // Calculate project metrics const metrics = calculateProjectMetrics(fileResults, duplicateGroups, allBlocks); const analysisTime = Date.now() - startTime; console.log(`✅ Analysis completed in ${(analysisTime / 1000).toFixed(1)}s`); return { summary: { projectPath, filesAnalyzed: files.length, blocksAnalyzed: allBlocks.length, duplicateGroups: duplicateGroups.length, wetScore: metrics.wetScore, dryScore: 100 - metrics.wetScore, wetGrade: getWetGrade(metrics.wetScore), dryGrade: getDryGrade(100 - metrics.wetScore), analysisTime, ...metrics }, duplicateGroups, recommendations, fileResults, topOffenders: identifyTopOffenders(duplicateGroups) }; } catch (error) { qerrors.default(error, 'analyzeProjectWetCodeImproved failed', { projectPath }); throw error; } } module.exports = analyzeProjectWetCodeImproved;