UNPKG

agentsqripts

Version:

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

181 lines (161 loc) 6.38 kB
/** * @file Heavy loop detector for CPU-intensive operation identification and scalability optimization * @description Single responsibility: Detect CPU-intensive operations that block request processing and reduce scalability * * This detector identifies computationally expensive loop operations that can block the event * loop in Node.js applications, preventing concurrent request handling and reducing overall * application throughput. It provides context-aware analysis to distinguish between * problematic blocking operations and acceptable computational patterns. * * Design rationale: * - Context-aware analysis prevents false positives in appropriate usage scenarios (CLI tools, batch processing) * - Pattern-based detection efficiently identifies CPU-intensive loop constructs * - Request path analysis focuses on scalability-critical code sections * - Performance impact assessment provides severity levels based on operation complexity * - Integration with execution context detection enables appropriate recommendations * * Heavy loop detection scope: * - Nested loops with high computational complexity (O(n²) or worse) * - Synchronous operations within loops that block event loop execution * - Large iteration counts in request-critical code paths * - CPU-intensive algorithms within web server request handlers * - Blocking operations that prevent concurrent request processing */ const { detectExecutionContext, getContextualScalabilityConcerns } = require('./contextDetector'); /** * Detects CPU-intensive operations in request paths * @param {string} content - File content * @param {string} filePath - Path to the file * @returns {Array} Array of CPU-bound issues */ function detectHeavyLoops(content, filePath) { const issues = []; const context = detectExecutionContext(content, filePath); const concerns = getContextualScalabilityConcerns(context); // Skip if CPU-intensive operations aren't a concern for this context if (!concerns.cpuIntensiveOperations.relevant) { return issues; } const hasLoop = /for\s*\(\s*(let|const|var)\s+/.test(content) || /\.map\s*\(/.test(content) || /\.reduce\s*\(/.test(content) || /\.forEach\s*\(/.test(content); const hasAwait = content.includes('await'); const hasSync = content.includes('Sync('); if (hasLoop && (hasAwait || hasSync)) { // Enhanced analysis for library context - distinguish analysis work from problematic patterns if (context.type === 'library') { const isLegitimateAnalysisWork = analyzeForLegitimateAnalysisWork(content, filePath); if (isLegitimateAnalysisWork) { // Skip flagging legitimate analysis work in analysis libraries // These tools are expected to do computational work for parsing/analysis return issues; } } const severity = concerns.cpuIntensiveOperations.severity; const contextualGuidance = getCPUIntensiveGuidance(context); issues.push({ type: 'cpu_bound_loop', severity, category: context.isServer ? 'API' : 'Performance', location: filePath, pattern: 'Heavy Loop', summary: `CPU-intensive loop detected in ${context.type} context`, recommendation: contextualGuidance.recommendation, impact: contextualGuidance.impact, context: { type: context.type, confidence: context.confidence, reason: concerns.cpuIntensiveOperations.reason } }); } return issues; } /** * Analyzes if CPU-intensive loop is legitimate analysis work * @param {string} content - File content * @param {string} filePath - File path for context * @returns {boolean} True if this appears to be legitimate analysis work */ function analyzeForLegitimateAnalysisWork(content, filePath) { // Check if this is in an analysis-related path const analysisPathPatterns = [ /\/ast\//, /\/analyze/, /\/detect/, /\/extract/, /\/parse/, /analyzer\.js$/, /detector\.js$/ ]; const isAnalysisPath = analysisPathPatterns.some(pattern => pattern.test(filePath)); // Check for analysis-related content patterns const analysisContentPatterns = [ // AST and parsing work /ast\./i, /parse\w*/i, /traverse/i, /acorn\./, /node\.type/i, // Code analysis patterns /analyze\w*/i, /detect\w*/i, /extract\w*/i, /pattern/i, /similarity/i, /complexity/i, // File processing for analysis /readFileSync.*analyze/i, /\.js.*content/i, /source.*code/i ]; const hasAnalysisContent = analysisContentPatterns.some(pattern => pattern.test(content)); // Patterns that indicate non-analysis CPU work (should still be flagged) const nonAnalysisPatterns = [ // Data processing without analysis purpose /crypto\./, /hash\w*\(/, /sort\(\)/, /mathematical.*computation/i, // Image/media processing /image\w*/i, /video\w*/i, /audio\w*/i ]; const hasNonAnalysisWork = nonAnalysisPatterns.some(pattern => pattern.test(content)); // Consider it legitimate analysis work if it's in analysis path/content and not doing non-analysis work return (isAnalysisPath || hasAnalysisContent) && !hasNonAnalysisWork; } /** * Gets contextual guidance for CPU-intensive operations * @param {Object} context - Execution context * @returns {Object} Contextual recommendation and impact */ function getCPUIntensiveGuidance(context) { switch (context.type) { case 'server': return { recommendation: 'Consider streaming, chunking, worker threads, or async batching to avoid blocking', impact: 'Can block event loop and cause request timeouts' }; case 'cli': return { recommendation: 'Consider progress indicators for long-running operations', impact: 'Expected behavior for analysis tools' }; case 'library': return { recommendation: 'Provide async/streaming alternatives for large datasets', impact: 'May block consumers depending on their usage context' }; default: return { recommendation: 'Consider async alternatives to avoid blocking', impact: 'Can block execution depending on usage context' }; } } module.exports = { detectHeavyLoops };