agentsqripts
Version:
Comprehensive static code analysis toolkit for identifying technical debt, security vulnerabilities, performance issues, and code quality problems
103 lines (88 loc) • 3.15 kB
JavaScript
/**
* @file Waterfall fetch detector
* @description Detects waterfall data fetching patterns
*/
/**
* Detects waterfall data fetching patterns
* @param {string} content - File content
* @param {string} filePath - Path to the file
* @returns {Array} Array of waterfall fetch issues
*/
function detectWaterfallFetch(content, filePath) {
const issues = [];
const lines = content.split('\n');
const { PERFORMANCE_PATTERNS } = require('./performancePatterns');
// Track async functions and their fetch calls
let currentFunction = null;
let functionStartLine = 0;
let fetchCalls = [];
lines.forEach((line, index) => {
const lineNumber = index + 1;
const trimmedLine = line.trim();
// Detect async function start
if (/async\s+function|async\s*\(|async\s+\w+\s*=>/.test(trimmedLine)) {
// Save previous function's fetch calls if any
if (currentFunction && fetchCalls.length > 1) {
checkForWaterfall(fetchCalls);
}
currentFunction = trimmedLine;
functionStartLine = lineNumber;
fetchCalls = [];
}
// Detect function end
if (currentFunction && (trimmedLine === '}' || trimmedLine === '};')) {
if (fetchCalls.length > 1) {
checkForWaterfall(fetchCalls);
}
currentFunction = null;
fetchCalls = [];
}
// Detect fetch calls with await
if (currentFunction && /await\s+(fetch|axios\.|api\.|http\.)/.test(line)) {
fetchCalls.push({
line: lineNumber,
code: line.trim(),
hasAwait: true
});
}
});
function checkForWaterfall(calls) {
// Check if fetches are sequential (waterfall)
let sequentialCount = 0;
for (let i = 0; i < calls.length - 1; i++) {
const current = calls[i];
const next = calls[i + 1];
// If next fetch is within 5 lines and both have await, likely waterfall
if (next.line - current.line <= 5 && current.hasAwait && next.hasAwait) {
sequentialCount++;
}
}
// If we have 2+ sequential fetches, report waterfall pattern
if (sequentialCount >= 1) {
const pattern = PERFORMANCE_PATTERNS['waterfall_fetch'];
issues.push({
type: 'waterfall_fetch',
severity: pattern.severity,
category: pattern.category,
location: `${filePath}:${calls[0].line}-${calls[calls.length - 1].line}`,
line: calls[0].line,
fetchCount: calls.length,
code: calls.map(c => c.code).join('\n'),
description: `Sequential data fetching (${calls.length} requests) creates waterfall effect`,
summary: `Waterfall pattern with ${calls.length} sequential fetches`,
recommendation: 'Use Promise.all() to fetch data concurrently when requests are independent',
effort: pattern.effort,
impact: pattern.impact,
estimatedSavings: '50-80% reduction in loading time'
});
}
}
// Check last function if file ends
if (currentFunction && fetchCalls.length > 1) {
checkForWaterfall(fetchCalls);
}
return issues;
}
module.exports = {
detectWaterfallFetch
};