{
  "dimension": "performance",
  "prefix": "PERF",
  "description": "Rules for detecting performance issues including inefficient algorithms, memory leaks, and resource waste",
  "rules": [
    {
      "id": "nested-loops",
      "category": "algorithm-complexity",
      "severity": "medium",
      "pattern": "for\\s*\\([^)]+\\)\\s*\\{[^}]*for\\s*\\([^)]+\\)|forEach\\s*\\([^)]+\\)\\s*\\{[^}]*forEach",
      "patternType": "regex",
      "description": "Nested loops may indicate O(n^2) or worse complexity. Consider if this can be optimized",
      "recommendation": "Use Map/Set for O(1) lookups, break early when possible, or restructure the algorithm",
      "fixExample": "// Before - O(n^2)\nfor (const a of listA) {\n  for (const b of listB) {\n    if (a.id === b.id) { ... }\n  }\n}\n\n// After - O(n)\nconst bMap = new Map(listB.map(b => [b.id, b]));\nfor (const a of listA) {\n  const b = bMap.get(a.id);\n  if (b) { ... }\n}"
    },
    {
      "id": "array-in-loop",
      "category": "inefficient-operation",
      "severity": "high",
      "pattern": "\\.includes\\s*\\(|indexOf\\s*\\(|find\\s*\\(",
      "patternType": "includes",
      "contextPattern": "for|while|forEach|map|filter|reduce",
      "description": "Array search methods inside loops cause O(n*m) complexity. Consider using Set or Map",
      "recommendation": "Convert array to Set before the loop for O(1) lookups",
      "fixExample": "// Before - O(n*m)\nfor (const item of items) {\n  if (existingIds.includes(item.id)) { ... }\n}\n\n// After - O(n)\nconst idSet = new Set(existingIds);\nfor (const item of items) {\n  if (idSet.has(item.id)) { ... }\n}"
    },
    {
      "id": "synchronous-io",
      "category": "io-efficiency",
      "severity": "high",
      "pattern": "readFileSync|writeFileSync|execSync|spawnSync",
      "patternType": "includes",
      "description": "Synchronous I/O blocks the event loop and degrades application responsiveness",
      "recommendation": "Use async versions (readFile, writeFile) or Promise-based APIs",
      "fixExample": "// Before\nconst data = fs.readFileSync(path);\n\n// After\nconst data = await fs.promises.readFile(path);\n// or\nfs.readFile(path, (err, data) => { ... });"
    },
    {
      "id": "memory-leak-closure",
      "category": "memory-leak",
      "severity": "high",
      "pattern": "addEventListener\\s*\\(|setInterval\\s*\\(|setTimeout\\s*\\(",
      "patternType": "regex",
      "negativePatterns": ["removeEventListener", "clearInterval", "clearTimeout"],
      "description": "Event listeners and timers without cleanup can cause memory leaks",
      "recommendation": "Always remove event listeners and clear timers in cleanup functions (componentWillUnmount, useEffect cleanup)",
      "fixExample": "// Before\nuseEffect(() => {\n  window.addEventListener('resize', handler);\n}, []);\n\n// After\nuseEffect(() => {\n  window.addEventListener('resize', handler);\n  return () => window.removeEventListener('resize', handler);\n}, []);"
    },
    {
      "id": "unnecessary-rerender",
      "category": "react-performance",
      "severity": "medium",
      "pattern": "useState\\s*\\(\\s*\\{|useState\\s*\\(\\s*\\[",
      "patternType": "regex",
      "description": "Creating new object/array references in useState can cause unnecessary re-renders",
      "recommendation": "Use useMemo for computed values, useCallback for functions, or consider state management libraries",
      "fixExample": "// Before - new object every render\nconst [config] = useState({ theme: 'dark' });\n\n// After - stable reference\nconst defaultConfig = useMemo(() => ({ theme: 'dark' }), []);\nconst [config] = useState(defaultConfig);"
    }
  ]
}
