agentsqripts
Version:
Comprehensive static code analysis toolkit for identifying technical debt, security vulnerabilities, performance issues, and code quality problems
194 lines (174 loc) • 6.7 kB
JavaScript
/**
* @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) {
// Enhanced analysis path detection
const analysisPathPatterns = [
/\/ast\//,
/\/analyze/,
/\/detect/,
/\/extract/,
/\/parse/,
/\/lib\/.*analyzer\.js$/,
/\/lib\/.*detector\.js$/,
/\/lib\/.*analysis/,
/\/scalability\//,
/\/security-vulns\//,
/\/performance\//,
/\/static-bugs\//,
/\/wet-code\//,
/\/cleanup\//,
/\/comment-analysis\//,
/\/frontend-backend\//,
/\/ui-problems\//,
/\/srp-violations\//,
/\/export-promotion\//,
/\/utils\/.*Helper/
];
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
};