UNPKG

agentsqripts

Version:

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

67 lines (60 loc) 2.27 kB
/** * @file Detect React hooks violations * @description Single responsibility: Detect conditional hooks and hooks in loops */ const walk = require('acorn-walk'); const { getLineNumber } = require('../../../utils/astParser'); /** * Detect hooks violations (conditional hooks, hooks in loops) * @param {Object} ast - AST tree * @param {string} filePath - File path * @returns {Array} Detected bugs */ function detectHooksViolations(ast, filePath) { const bugs = []; const hookNames = ['useState', 'useEffect', 'useCallback', 'useMemo', 'useRef', 'useContext']; walk.ancestor(ast, { CallExpression(node, ancestors) { if (node.callee.type === 'Identifier' && hookNames.includes(node.callee.name)) { // Check if hook is inside a condition or loop for (let i = ancestors.length - 1; i >= 0; i--) { const ancestor = ancestors[i]; if (ancestor.type === 'IfStatement' || ancestor.type === 'ConditionalExpression') { bugs.push({ type: 'conditional_hook', severity: 'HIGH', category: 'React', line: getLineNumber(node), column: node.loc ? node.loc.start.column : 0, description: `React Hook "${node.callee.name}" called conditionally`, recommendation: 'Move the hook to the top level of the component', effort: 2, impact: 'high', file: filePath }); break; } if (ancestor.type === 'ForStatement' || ancestor.type === 'WhileStatement' || ancestor.type === 'DoWhileStatement') { bugs.push({ type: 'hook_in_loop', severity: 'HIGH', category: 'React', line: getLineNumber(node), column: node.loc ? node.loc.start.column : 0, description: `React Hook "${node.callee.name}" called in a loop`, recommendation: 'Move the hook outside the loop', effort: 2, impact: 'high', file: filePath }); break; } } } } }); return bugs; } module.exports = detectHooksViolations;