UNPKG

agentsqripts

Version:

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

128 lines (122 loc) 5.84 kB
/** * @file Detect legacy callback-based async patterns for modernization * @description Single responsibility: Identify callback patterns that could benefit from async/await * * This detector analyzes JavaScript code for legacy callback-based asynchronous patterns, * particularly Node.js-style error-first callbacks and nested callback structures * (callback hell). It helps identify opportunities to modernize codebases with * Promise-based patterns and async/await syntax for improved maintainability. * * Design rationale: * - Focuses on two main problematic patterns: error-first callbacks and callback nesting * - Uses regex pattern matching for efficient detection across large codebases * - Provides specific modernization recommendations based on detected patterns * - Categorizes issues by severity to help prioritize refactoring efforts */ /** * Detect callback-based async patterns that could be modernized * * Technical function: Scans code lines for legacy callback patterns and nesting issues * * Implementation rationale: * - Line-by-line analysis provides precise location information for issues * - Regex patterns efficiently identify callback signatures and nesting structures * - Severity differentiation helps prioritize refactoring (callback hell > simple callbacks) * - Comprehensive issue objects provide context and actionable recommendations * * Pattern detection strategy: * - Error-first callback pattern: `function(err, ...)` or `(err, ...)` arrow functions * - Nested callback detection: Multiple function declarations within single line * - Whitespace normalization handles various coding styles and formatting * - Conservative matching prevents false positives while catching common patterns * * Regex pattern breakdown: * - `\w+\s*\([^)]*,\s*function\s*\(\s*err\s*,`: Named function with error-first callback * - `\w+\s*\([^)]*,\s*\(\s*err\s*,`: Function call with arrow function error-first callback * - `function\s*\([^)]*\)\s*{.*function\s*\([^)]*\)\s*{`: Nested function declarations * * Severity classification rationale: * - Callback patterns (LOW): Modernization improves maintainability but not critical * - Callback hell (MEDIUM): Significantly impacts code readability and error handling * - Effort estimates based on typical refactoring complexity for each pattern type * * Modernization recommendations: * - Simple callbacks: Use util.promisify() or native Promise-based APIs * - Callback hell: Refactor to async/await with proper error handling * - Focus on maintainability improvements rather than performance gains * * Performance considerations: * - O(n) time complexity for single pass through all code lines * - Regex compilation cached by JavaScript engine for repeated patterns * - Memory usage scales linearly with number of detected issues * - Early continue optimization when no patterns match * * Limitations and trade-offs: * - Line-based analysis may miss multi-line callback patterns * - Regex matching may have false positives in comments or strings * - Simple pattern detection chosen over AST parsing for performance * - Focus on common Node.js patterns rather than all possible callback styles * * Alternative approaches considered: * - AST-based analysis: Rejected for performance overhead in large codebases * - Multi-line pattern detection: Rejected for complexity vs benefit trade-off * - Framework-specific callback detection: Rejected to maintain general applicability * * @param {string[]} lines - Array of code lines to analyze for callback patterns * @param {string} filePath - File path for issue location reporting * @returns {Array<Object>} Array of detected callback-related issues with modernization recommendations * @example * // For: fs.readFile('file.txt', function(err, data) { ... }) * [{ * type: 'callback_pattern', * severity: 'LOW', * location: 'src/file.js:10', * description: 'Callback-based async pattern - consider modernizing to async/await', * recommendation: 'Consider using promisify() or native Promise-based APIs' * }] */ function detectAsyncCallbacks(lines, filePath) { const issues = []; for (let i = 0; i < lines.length; i++) { const line = lines[i]; const lineNumber = i + 1; const trimmed = line.trim(); // Node.js callback patterns if (/\w+\s*\([^)]*,\s*function\s*\(\s*err\s*,/.test(trimmed) || /\w+\s*\([^)]*,\s*\(\s*err\s*,/.test(trimmed)) { issues.push({ type: 'callback_pattern', severity: 'LOW', category: 'Async', location: `${filePath}:${lineNumber}`, line: lineNumber, code: trimmed, description: 'Callback-based async pattern - consider modernizing to async/await', summary: 'Legacy callback pattern detected', recommendation: 'Consider using promisify() or native Promise-based APIs', effort: 2, impact: 'Modernizes codebase and improves error handling', estimatedSavings: 'improved maintainability' }); } // Nested callbacks (callback hell) if (/function\s*\([^)]*\)\s*{.*function\s*\([^)]*\)\s*{/.test(trimmed)) { issues.push({ type: 'callback_hell', severity: 'MEDIUM', category: 'Async', location: `${filePath}:${lineNumber}`, line: lineNumber, code: trimmed, description: 'Nested callbacks detected - callback hell pattern', summary: 'Callback hell pattern', recommendation: 'Refactor to async/await or Promise chains', effort: 3, impact: 'Significantly improves code readability and maintainability', estimatedSavings: 'major maintainability improvement' }); } } return issues; } module.exports = detectAsyncCallbacks;