agentsqripts
Version:
Comprehensive static code analysis toolkit for identifying technical debt, security vulnerabilities, performance issues, and code quality problems
55 lines (46 loc) • 1.86 kB
JavaScript
/**
* @file Detect unmemoized callbacks
* @description Single responsibility: Identify callbacks that should use useCallback
*/
const { iterateLines } = require('../../utils/patternDetector');
const isInsideComponent = require('./isInsideComponent');
const extractFunctionName = require('./extractFunctionName');
const isFunctionPassedAsProp = require('./isFunctionPassedAsProp');
/**
* Detect unmemoized callbacks passed as props
*/
function detectUnmemoizedCallbacks(lines, filePath) {
const issues = [];
iterateLines(lines, (line, lineNumber, trimmed, i) => {
// Function declarations inside components
if ((trimmed.startsWith('const ') && trimmed.includes('= (') ||
trimmed.startsWith('function ')) &&
isInsideComponent(lines, i)) {
const funcName = extractFunctionName(trimmed);
// Check if this function is passed as a prop
if (funcName && isFunctionPassedAsProp(lines, funcName)) {
const hasUseCallback = lines.some(l =>
l.includes('useCallback') && l.includes(funcName)
);
if (!hasUseCallback) {
issues.push({
type: 'unmemoized_callback',
severity: 'MEDIUM',
category: 'React',
location: `${filePath}:${lineNumber}`,
line: lineNumber,
code: trimmed,
description: 'Callback function recreated on every render when passed as prop',
summary: 'Unmemoized callback prop',
recommendation: 'Wrap callback with useCallback to prevent child re-renders',
effort: 1,
impact: 'Prevents unnecessary child component re-renders',
estimatedSavings: '30-50% child re-render reduction'
});
}
}
}
});
return issues;
}
module.exports = detectUnmemoizedCallbacks;