react-doctor 0.0.31 → 0.0.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -2
- package/dist/cli.js +226 -434
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +108 -79
- package/dist/index.js.map +1 -1
- package/dist/react-doctor-plugin.js +41 -10
- package/dist/react-doctor-plugin.js.map +1 -1
- package/package.json +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react-doctor-plugin.js","names":[],"sources":["../src/plugin/constants.ts","../src/plugin/helpers.ts","../src/plugin/rules/architecture.ts","../src/plugin/rules/bundle-size.ts","../src/plugin/rules/client.ts","../src/plugin/rules/correctness.ts","../src/plugin/rules/js-performance.ts","../src/plugin/rules/nextjs.ts","../src/plugin/rules/performance.ts","../src/plugin/rules/react-native.ts","../src/plugin/rules/security.ts","../src/plugin/rules/server.ts","../src/plugin/rules/state-and-effects.ts","../src/plugin/index.ts"],"sourcesContent":["export const GIANT_COMPONENT_LINE_THRESHOLD = 300;\nexport const CASCADING_SET_STATE_THRESHOLD = 3;\nexport const RELATED_USE_STATE_THRESHOLD = 5;\nexport const DEEP_NESTING_THRESHOLD = 3;\nexport const DUPLICATE_STORAGE_READ_THRESHOLD = 2;\nexport const SEQUENTIAL_AWAIT_THRESHOLD = 3;\nexport const SECRET_MIN_LENGTH_CHARS = 8;\nexport const AUTH_CHECK_LOOKAHEAD_STATEMENTS = 3;\n\nexport const LAYOUT_PROPERTIES = new Set([\n \"width\",\n \"height\",\n \"top\",\n \"left\",\n \"right\",\n \"bottom\",\n \"padding\",\n \"paddingTop\",\n \"paddingRight\",\n \"paddingBottom\",\n \"paddingLeft\",\n \"margin\",\n \"marginTop\",\n \"marginRight\",\n \"marginBottom\",\n \"marginLeft\",\n \"borderWidth\",\n \"fontSize\",\n \"lineHeight\",\n \"gap\",\n]);\n\nexport const MOTION_ANIMATE_PROPS = new Set([\n \"animate\",\n \"initial\",\n \"exit\",\n \"whileHover\",\n \"whileTap\",\n \"whileFocus\",\n \"whileDrag\",\n \"whileInView\",\n]);\n\nexport const HEAVY_LIBRARIES = new Set([\n \"@monaco-editor/react\",\n \"monaco-editor\",\n \"recharts\",\n \"@react-pdf/renderer\",\n \"react-quill\",\n \"@codemirror/view\",\n \"@codemirror/state\",\n \"chart.js\",\n \"react-chartjs-2\",\n \"@toast-ui/editor\",\n \"draft-js\",\n]);\n\nexport const FETCH_CALLEE_NAMES = new Set([\"fetch\"]);\nexport const FETCH_MEMBER_OBJECTS = new Set([\"axios\", \"ky\", \"got\"]);\nexport const INDEX_PARAMETER_NAMES = new Set([\"index\", \"idx\", \"i\"]);\nexport const BARREL_INDEX_SUFFIXES = [\n \"/index\",\n \"/index.js\",\n \"/index.ts\",\n \"/index.tsx\",\n \"/index.mjs\",\n];\nexport const PASSIVE_EVENT_NAMES = new Set([\n \"scroll\",\n \"wheel\",\n \"touchstart\",\n \"touchmove\",\n \"touchend\",\n]);\n\nexport const LOOP_TYPES = [\n \"ForStatement\",\n \"ForInStatement\",\n \"ForOfStatement\",\n \"WhileStatement\",\n \"DoWhileStatement\",\n];\n\nexport const AUTH_FUNCTION_NAMES = new Set([\n \"auth\",\n \"getSession\",\n \"getServerSession\",\n \"getUser\",\n \"requireAuth\",\n \"checkAuth\",\n \"verifyAuth\",\n \"authenticate\",\n \"currentUser\",\n \"getAuth\",\n \"validateSession\",\n]);\n\nexport const SECRET_PATTERNS = [\n /^sk_live_/,\n /^sk_test_/,\n /^AKIA[0-9A-Z]{16}$/,\n /^ghp_[a-zA-Z0-9]{36}$/,\n /^gho_[a-zA-Z0-9]{36}$/,\n /^github_pat_/,\n /^glpat-/,\n /^xox[bporas]-/,\n /^sk-[a-zA-Z0-9]{32,}$/,\n];\n\nexport const SECRET_VARIABLE_PATTERN = /(?:api_?key|secret|token|password|credential|auth)/i;\n\nexport const SECRET_FALSE_POSITIVE_SUFFIXES = new Set([\n \"modal\",\n \"label\",\n \"text\",\n \"title\",\n \"name\",\n \"id\",\n \"key\",\n \"url\",\n \"path\",\n \"route\",\n \"page\",\n \"param\",\n \"field\",\n \"column\",\n \"header\",\n \"placeholder\",\n \"description\",\n \"type\",\n \"icon\",\n \"class\",\n \"style\",\n \"variant\",\n \"event\",\n \"action\",\n \"status\",\n \"state\",\n \"mode\",\n \"flag\",\n \"option\",\n \"config\",\n \"message\",\n \"error\",\n \"display\",\n \"view\",\n \"component\",\n \"element\",\n \"container\",\n \"wrapper\",\n \"button\",\n \"link\",\n \"input\",\n \"select\",\n \"dialog\",\n \"menu\",\n \"form\",\n \"step\",\n \"index\",\n \"count\",\n \"length\",\n \"role\",\n \"scope\",\n \"context\",\n \"provider\",\n \"ref\",\n \"handler\",\n \"query\",\n \"schema\",\n \"constant\",\n]);\n\nexport const LOADING_STATE_PATTERN = /^(?:isLoading|isPending)$/;\n\nexport const GENERIC_EVENT_SUFFIXES = new Set([\"Click\", \"Change\", \"Input\", \"Blur\", \"Focus\"]);\n\nexport const TRIVIAL_INITIALIZER_NAMES = new Set([\n \"Boolean\",\n \"String\",\n \"Number\",\n \"Array\",\n \"Object\",\n \"parseInt\",\n \"parseFloat\",\n]);\n\nexport const SETTER_PATTERN = /^set[A-Z]/;\nexport const RENDER_FUNCTION_PATTERN = /^render[A-Z]/;\nexport const UPPERCASE_PATTERN = /^[A-Z]/;\nexport const PAGE_FILE_PATTERN = /\\/page\\.(tsx?|jsx?)$/;\nexport const PAGE_OR_LAYOUT_FILE_PATTERN = /\\/(page|layout)\\.(tsx?|jsx?)$/;\n\nexport const INTERNAL_PAGE_PATH_PATTERN =\n /\\/(?:(?:\\((?:dashboard|admin|settings|account|internal|manage|console|portal|auth|onboarding|app|ee|protected)\\))|(?:dashboard|admin|settings|account|internal|manage|console|portal))\\//i;\n\nexport const TEST_FILE_PATTERN = /\\.(?:test|spec|stories)\\.[tj]sx?$/;\nexport const OG_ROUTE_PATTERN = /\\/og\\b/i;\n\nexport const PAGES_DIRECTORY_PATTERN = /\\/pages\\//;\nexport const SERVER_ACTION_FILE_PATTERN = /actions?\\.(tsx?|jsx?)$/;\nexport const SERVER_ACTION_DIRECTORY_PATTERN = /\\/actions\\//;\n\nexport const NEXTJS_NAVIGATION_FUNCTIONS = new Set([\n \"redirect\",\n \"permanentRedirect\",\n \"notFound\",\n \"forbidden\",\n \"unauthorized\",\n]);\n\nexport const GOOGLE_FONTS_PATTERN = /fonts\\.googleapis\\.com/;\n\nexport const POLYFILL_SCRIPT_PATTERN = /polyfill\\.io|polyfill\\.min\\.js|cdn\\.polyfill/;\n\nexport const EXECUTABLE_SCRIPT_TYPES = new Set([\n \"text/javascript\",\n \"application/javascript\",\n \"module\",\n]);\n\nexport const APP_DIRECTORY_PATTERN = /\\/app\\//;\n\nexport const ROUTE_HANDLER_FILE_PATTERN = /\\/route\\.(tsx?|jsx?)$/;\n\nexport const MUTATION_METHOD_NAMES = new Set([\n \"create\",\n \"insert\",\n \"insertInto\",\n \"update\",\n \"upsert\",\n \"delete\",\n \"remove\",\n \"destroy\",\n \"set\",\n \"append\",\n]);\n\nexport const MUTATING_HTTP_METHODS = new Set([\"POST\", \"PUT\", \"DELETE\", \"PATCH\"]);\n\nexport const MUTATING_ROUTE_SEGMENTS = new Set([\n \"logout\",\n \"log-out\",\n \"signout\",\n \"sign-out\",\n \"unsubscribe\",\n \"delete\",\n \"remove\",\n \"revoke\",\n \"cancel\",\n \"deactivate\",\n]);\n\nexport const EFFECT_HOOK_NAMES = new Set([\"useEffect\", \"useLayoutEffect\"]);\nexport const HOOKS_WITH_DEPS = new Set([\"useEffect\", \"useLayoutEffect\", \"useMemo\", \"useCallback\"]);\nexport const CHAINABLE_ITERATION_METHODS = new Set([\"map\", \"filter\", \"forEach\", \"flatMap\"]);\nexport const STORAGE_OBJECTS = new Set([\"localStorage\", \"sessionStorage\"]);\n\nexport const LARGE_BLUR_THRESHOLD_PX = 10;\nexport const BLUR_VALUE_PATTERN = /blur\\((\\d+(?:\\.\\d+)?)px\\)/;\nexport const ANIMATION_CALLBACK_NAMES = new Set([\"requestAnimationFrame\", \"setInterval\"]);\nexport const MOTION_LIBRARY_PACKAGES = new Set([\"framer-motion\", \"motion\"]);\n\nexport const RAW_TEXT_PREVIEW_MAX_CHARS = 30;\n\nexport const REACT_NATIVE_TEXT_COMPONENTS = new Set([\"Text\", \"TextInput\"]);\n\nexport const REACT_NATIVE_TEXT_COMPONENT_SUFFIXES = new Set([\n \"Text\",\n \"Title\",\n \"Label\",\n \"Heading\",\n \"Caption\",\n \"Subtitle\",\n]);\n\nexport const DEPRECATED_RN_MODULE_REPLACEMENTS: Record<string, string> = {\n AsyncStorage: \"@react-native-async-storage/async-storage\",\n Picker: \"@react-native-picker/picker\",\n PickerIOS: \"@react-native-picker/picker\",\n DatePickerIOS: \"@react-native-community/datetimepicker\",\n DatePickerAndroid: \"@react-native-community/datetimepicker\",\n ProgressBarAndroid: \"a community alternative\",\n ProgressViewIOS: \"a community alternative\",\n SafeAreaView: \"react-native-safe-area-context\",\n Slider: \"@react-native-community/slider\",\n ViewPagerAndroid: \"react-native-pager-view\",\n WebView: \"react-native-webview\",\n NetInfo: \"@react-native-community/netinfo\",\n CameraRoll: \"@react-native-camera-roll/camera-roll\",\n Clipboard: \"@react-native-clipboard/clipboard\",\n ImageEditor: \"@react-native-community/image-editor\",\n MaskedViewIOS: \"@react-native-masked-view/masked-view\",\n};\n\nexport const LEGACY_EXPO_PACKAGE_REPLACEMENTS: Record<string, string> = {\n \"expo-av\": \"expo-audio for audio and expo-video for video\",\n \"expo-permissions\": \"the permissions API in each module (e.g. Camera.requestPermissionsAsync())\",\n \"@expo/vector-icons\":\n \"expo-symbols or expo-image (see https://docs.expo.dev/versions/latest/sdk/symbols/)\",\n};\n\nexport const REACT_NATIVE_LIST_COMPONENTS = new Set([\n \"FlatList\",\n \"SectionList\",\n \"VirtualizedList\",\n \"FlashList\",\n]);\n\nexport const LEGACY_SHADOW_STYLE_PROPERTIES = new Set([\n \"shadowColor\",\n \"shadowOffset\",\n \"shadowOpacity\",\n \"shadowRadius\",\n \"elevation\",\n]);\n","import {\n FETCH_CALLEE_NAMES,\n FETCH_MEMBER_OBJECTS,\n LOOP_TYPES,\n MUTATING_HTTP_METHODS,\n MUTATION_METHOD_NAMES,\n SETTER_PATTERN,\n UPPERCASE_PATTERN,\n} from \"./constants.js\";\nimport type { EsTreeNode, RuleVisitors } from \"./types.js\";\n\nexport const walkAst = (node: EsTreeNode, visitor: (child: EsTreeNode) => void): void => {\n if (!node || typeof node !== \"object\") return;\n visitor(node);\n for (const key of Object.keys(node)) {\n if (key === \"parent\") continue;\n const child = node[key];\n if (Array.isArray(child)) {\n for (const item of child) {\n if (item && typeof item === \"object\" && item.type) {\n walkAst(item, visitor);\n }\n }\n } else if (child && typeof child === \"object\" && child.type) {\n walkAst(child, visitor);\n }\n }\n};\n\nexport const isSetterIdentifier = (name: string): boolean => SETTER_PATTERN.test(name);\n\nexport const isUppercaseName = (name: string): boolean => UPPERCASE_PATTERN.test(name);\n\nexport const isMemberProperty = (node: EsTreeNode, propertyName: string): boolean =>\n node.type === \"MemberExpression\" &&\n node.property?.type === \"Identifier\" &&\n node.property.name === propertyName;\n\nexport const getEffectCallback = (node: EsTreeNode): EsTreeNode | null => {\n if (!node.arguments?.length) return null;\n const callback = node.arguments[0];\n if (callback.type === \"ArrowFunctionExpression\" || callback.type === \"FunctionExpression\") {\n return callback;\n }\n return null;\n};\n\nexport const getCallbackStatements = (callback: EsTreeNode): EsTreeNode[] => {\n if (callback.body?.type === \"BlockStatement\") {\n return callback.body.body ?? [];\n }\n return callback.body ? [callback.body] : [];\n};\n\nexport const countSetStateCalls = (node: EsTreeNode): number => {\n let setStateCallCount = 0;\n walkAst(node, (child) => {\n if (\n child.type === \"CallExpression\" &&\n child.callee?.type === \"Identifier\" &&\n isSetterIdentifier(child.callee.name)\n ) {\n setStateCallCount++;\n }\n });\n return setStateCallCount;\n};\n\nexport const isSimpleExpression = (node: EsTreeNode | null): boolean => {\n if (!node) return false;\n switch (node.type) {\n case \"Identifier\":\n case \"Literal\":\n case \"TemplateLiteral\":\n return true;\n case \"BinaryExpression\":\n return isSimpleExpression(node.left) && isSimpleExpression(node.right);\n case \"UnaryExpression\":\n return isSimpleExpression(node.argument);\n case \"MemberExpression\":\n return !node.computed;\n case \"ConditionalExpression\":\n return (\n isSimpleExpression(node.test) &&\n isSimpleExpression(node.consequent) &&\n isSimpleExpression(node.alternate)\n );\n default:\n return false;\n }\n};\n\nexport const isComponentDeclaration = (node: EsTreeNode): boolean =>\n node.type === \"FunctionDeclaration\" && Boolean(node.id?.name) && isUppercaseName(node.id.name);\n\nexport const isComponentAssignment = (node: EsTreeNode): boolean =>\n node.type === \"VariableDeclarator\" &&\n node.id?.type === \"Identifier\" &&\n isUppercaseName(node.id.name) &&\n Boolean(node.init) &&\n (node.init.type === \"ArrowFunctionExpression\" || node.init.type === \"FunctionExpression\");\n\nexport const isHookCall = (node: EsTreeNode, hookName: string | Set<string>): boolean =>\n node.type === \"CallExpression\" &&\n node.callee?.type === \"Identifier\" &&\n (typeof hookName === \"string\" ? node.callee.name === hookName : hookName.has(node.callee.name));\n\nexport const hasDirective = (programNode: EsTreeNode, directive: string): boolean =>\n Boolean(\n programNode.body?.some(\n (statement: EsTreeNode) =>\n statement.type === \"ExpressionStatement\" &&\n statement.expression?.type === \"Literal\" &&\n statement.expression.value === directive,\n ),\n );\n\nexport const hasUseServerDirective = (node: EsTreeNode): boolean => {\n if (node.body?.type !== \"BlockStatement\") return false;\n return Boolean(\n node.body.body?.some(\n (statement: EsTreeNode) =>\n statement.type === \"ExpressionStatement\" && statement.directive === \"use server\",\n ),\n );\n};\n\nexport const containsFetchCall = (node: EsTreeNode): boolean => {\n let didFindFetchCall = false;\n walkAst(node, (child) => {\n if (didFindFetchCall || child.type !== \"CallExpression\") return;\n if (child.callee?.type === \"Identifier\" && FETCH_CALLEE_NAMES.has(child.callee.name)) {\n didFindFetchCall = true;\n }\n if (\n child.callee?.type === \"MemberExpression\" &&\n child.callee.object?.type === \"Identifier\" &&\n FETCH_MEMBER_OBJECTS.has(child.callee.object.name)\n ) {\n didFindFetchCall = true;\n }\n });\n return didFindFetchCall;\n};\n\nexport const findJsxAttribute = (\n attributes: EsTreeNode[],\n attributeName: string,\n): EsTreeNode | undefined =>\n attributes?.find(\n (attr: EsTreeNode) =>\n attr.type === \"JSXAttribute\" &&\n attr.name?.type === \"JSXIdentifier\" &&\n attr.name.name === attributeName,\n );\n\nexport const hasJsxAttribute = (attributes: EsTreeNode[], attributeName: string): boolean =>\n Boolean(findJsxAttribute(attributes, attributeName));\n\nexport const createLoopAwareVisitors = (\n innerVisitors: Record<string, (node: EsTreeNode) => void>,\n): RuleVisitors => {\n let loopDepth = 0;\n const incrementLoopDepth = (): void => {\n loopDepth++;\n };\n const decrementLoopDepth = (): void => {\n loopDepth--;\n };\n\n const visitors: RuleVisitors = {};\n\n for (const loopType of LOOP_TYPES) {\n visitors[loopType] = incrementLoopDepth;\n visitors[`${loopType}:exit`] = decrementLoopDepth;\n }\n\n for (const [nodeType, handler] of Object.entries(innerVisitors)) {\n visitors[nodeType] = (node: EsTreeNode) => {\n if (loopDepth > 0) handler(node);\n };\n }\n\n return visitors;\n};\n\nconst isCookiesOrHeadersCall = (node: EsTreeNode, methodName: string): boolean => {\n if (node.type !== \"CallExpression\" || node.callee?.type !== \"MemberExpression\") return false;\n const { object, property } = node.callee;\n if (property?.type !== \"Identifier\" || !MUTATION_METHOD_NAMES.has(property.name)) return false;\n if (object?.type !== \"CallExpression\" || object.callee?.type !== \"Identifier\") return false;\n return object.callee.name === methodName;\n};\n\nconst isMutatingDbCall = (node: EsTreeNode): boolean => {\n if (node.type !== \"CallExpression\" || node.callee?.type !== \"MemberExpression\") return false;\n const { property } = node.callee;\n return property?.type === \"Identifier\" && MUTATION_METHOD_NAMES.has(property.name);\n};\n\nconst isMutatingFetchCall = (node: EsTreeNode): boolean => {\n if (node.type !== \"CallExpression\") return false;\n if (node.callee?.type !== \"Identifier\" || node.callee.name !== \"fetch\") return false;\n const optionsArgument = node.arguments?.[1];\n if (!optionsArgument || optionsArgument.type !== \"ObjectExpression\") return false;\n return optionsArgument.properties?.some(\n (property: EsTreeNode) =>\n property.type === \"Property\" &&\n property.key?.type === \"Identifier\" &&\n property.key.name === \"method\" &&\n property.value?.type === \"Literal\" &&\n typeof property.value.value === \"string\" &&\n MUTATING_HTTP_METHODS.has(property.value.value.toUpperCase()),\n );\n};\n\nexport const findSideEffect = (node: EsTreeNode): string | null => {\n let sideEffectDescription: string | null = null;\n walkAst(node, (child: EsTreeNode) => {\n if (sideEffectDescription) return;\n if (isCookiesOrHeadersCall(child, \"cookies\")) {\n const methodName = child.callee.property.name;\n sideEffectDescription = `cookies().${methodName}()`;\n } else if (isCookiesOrHeadersCall(child, \"headers\")) {\n const methodName = child.callee.property.name;\n sideEffectDescription = `headers().${methodName}()`;\n } else if (isMutatingFetchCall(child)) {\n const methodProperty = child.arguments[1].properties.find(\n (property: EsTreeNode) =>\n property.key?.type === \"Identifier\" && property.key.name === \"method\",\n );\n sideEffectDescription = `fetch() with method ${methodProperty.value.value}`;\n } else if (isMutatingDbCall(child)) {\n const methodName = child.callee.property.name;\n const objectName =\n child.callee.object?.type === \"Identifier\" ? child.callee.object.name : null;\n sideEffectDescription = objectName ? `${objectName}.${methodName}()` : `.${methodName}()`;\n }\n });\n return sideEffectDescription;\n};\n\nexport const extractDestructuredPropNames = (params: EsTreeNode[]): Set<string> => {\n const propNames = new Set<string>();\n for (const param of params) {\n if (param.type === \"ObjectPattern\") {\n for (const property of param.properties ?? []) {\n if (property.type === \"Property\" && property.key?.type === \"Identifier\") {\n propNames.add(property.key.name);\n }\n }\n } else if (param.type === \"Identifier\") {\n propNames.add(param.name);\n }\n }\n return propNames;\n};\n","import {\n GENERIC_EVENT_SUFFIXES,\n GIANT_COMPONENT_LINE_THRESHOLD,\n RENDER_FUNCTION_PATTERN,\n} from \"../constants.js\";\nimport { isComponentAssignment, isComponentDeclaration, isUppercaseName } from \"../helpers.js\";\nimport type { EsTreeNode, Rule, RuleContext } from \"../types.js\";\n\nexport const noGenericHandlerNames: Rule = {\n create: (context: RuleContext) => ({\n JSXAttribute(node: EsTreeNode) {\n if (node.name?.type !== \"JSXIdentifier\" || !node.name.name.startsWith(\"on\")) return;\n if (!node.value || node.value.type !== \"JSXExpressionContainer\") return;\n\n const eventSuffix = node.name.name.slice(2);\n if (!GENERIC_EVENT_SUFFIXES.has(eventSuffix)) return;\n\n const mirroredHandlerName = `handle${eventSuffix}`;\n const expression = node.value.expression;\n if (expression?.type === \"Identifier\" && expression.name === mirroredHandlerName) {\n context.report({\n node,\n message: `Non-descriptive handler name \"${expression.name}\" — name should describe what it does, not when it runs`,\n });\n }\n },\n }),\n};\n\nexport const noGiantComponent: Rule = {\n create: (context: RuleContext) => {\n const reportOversizedComponent = (\n nameNode: EsTreeNode,\n componentName: string,\n bodyNode: EsTreeNode,\n ): void => {\n if (!bodyNode.loc) return;\n const lineCount = bodyNode.loc.end.line - bodyNode.loc.start.line + 1;\n if (lineCount > GIANT_COMPONENT_LINE_THRESHOLD) {\n context.report({\n node: nameNode,\n message: `Component \"${componentName}\" is ${lineCount} lines — consider breaking it into smaller focused components`,\n });\n }\n };\n\n return {\n FunctionDeclaration(node: EsTreeNode) {\n if (!node.id?.name || !isUppercaseName(node.id.name)) return;\n reportOversizedComponent(node.id, node.id.name, node);\n },\n VariableDeclarator(node: EsTreeNode) {\n if (!isComponentAssignment(node)) return;\n reportOversizedComponent(node.id, node.id.name, node.init);\n },\n };\n },\n};\n\nexport const noRenderInRender: Rule = {\n create: (context: RuleContext) => ({\n JSXExpressionContainer(node: EsTreeNode) {\n const expression = node.expression;\n if (expression?.type !== \"CallExpression\") return;\n\n let calleeName: string | null = null;\n if (expression.callee?.type === \"Identifier\") {\n calleeName = expression.callee.name;\n } else if (\n expression.callee?.type === \"MemberExpression\" &&\n expression.callee.property?.type === \"Identifier\"\n ) {\n calleeName = expression.callee.property.name;\n }\n\n if (calleeName && RENDER_FUNCTION_PATTERN.test(calleeName)) {\n context.report({\n node: expression,\n message: `Inline render function \"${calleeName}()\" — extract to a separate component for proper reconciliation`,\n });\n }\n },\n }),\n};\n\nexport const noNestedComponentDefinition: Rule = {\n create: (context: RuleContext) => {\n const componentStack: string[] = [];\n\n return {\n FunctionDeclaration(node: EsTreeNode) {\n if (!isComponentDeclaration(node)) return;\n if (componentStack.length > 0) {\n context.report({\n node: node.id,\n message: `Component \"${node.id.name}\" defined inside \"${componentStack[componentStack.length - 1]}\" — creates new instance every render, destroying state`,\n });\n }\n componentStack.push(node.id.name);\n },\n \"FunctionDeclaration:exit\"(node: EsTreeNode) {\n if (isComponentDeclaration(node)) componentStack.pop();\n },\n VariableDeclarator(node: EsTreeNode) {\n if (!isComponentAssignment(node)) return;\n if (componentStack.length > 0) {\n context.report({\n node: node.id,\n message: `Component \"${node.id.name}\" defined inside \"${componentStack[componentStack.length - 1]}\" — creates new instance every render, destroying state`,\n });\n }\n componentStack.push(node.id.name);\n },\n \"VariableDeclarator:exit\"(node: EsTreeNode) {\n if (isComponentAssignment(node)) componentStack.pop();\n },\n };\n },\n};\n","import { BARREL_INDEX_SUFFIXES, HEAVY_LIBRARIES } from \"../constants.js\";\nimport { findJsxAttribute, hasJsxAttribute } from \"../helpers.js\";\nimport type { EsTreeNode, Rule, RuleContext } from \"../types.js\";\n\nexport const noBarrelImport: Rule = {\n create: (context: RuleContext) => {\n let didReportForFile = false;\n\n return {\n ImportDeclaration(node: EsTreeNode) {\n if (didReportForFile) return;\n\n const source = node.source?.value;\n if (typeof source !== \"string\" || !source.startsWith(\".\")) return;\n\n if (BARREL_INDEX_SUFFIXES.some((suffix) => source.endsWith(suffix))) {\n didReportForFile = true;\n context.report({\n node,\n message:\n \"Import from barrel/index file — import directly from the source module for better tree-shaking\",\n });\n }\n },\n };\n },\n};\n\nexport const noFullLodashImport: Rule = {\n create: (context: RuleContext) => ({\n ImportDeclaration(node: EsTreeNode) {\n const source = node.source?.value;\n if (source === \"lodash\" || source === \"lodash-es\") {\n context.report({\n node,\n message: \"Importing entire lodash library — import from 'lodash/functionName' instead\",\n });\n }\n },\n }),\n};\n\nexport const noMoment: Rule = {\n create: (context: RuleContext) => ({\n ImportDeclaration(node: EsTreeNode) {\n if (node.source?.value === \"moment\") {\n context.report({\n node,\n message: 'moment.js is 300kb+ — use \"date-fns\" or \"dayjs\" instead',\n });\n }\n },\n }),\n};\n\nexport const preferDynamicImport: Rule = {\n create: (context: RuleContext) => ({\n ImportDeclaration(node: EsTreeNode) {\n const source = node.source?.value;\n if (typeof source === \"string\" && HEAVY_LIBRARIES.has(source)) {\n context.report({\n node,\n message: `\"${source}\" is a heavy library — use React.lazy() or next/dynamic for code splitting`,\n });\n }\n },\n }),\n};\n\nexport const useLazyMotion: Rule = {\n create: (context: RuleContext) => ({\n ImportDeclaration(node: EsTreeNode) {\n const source = node.source?.value;\n if (source !== \"framer-motion\" && source !== \"motion/react\") return;\n\n const hasFullMotionImport = node.specifiers?.some(\n (specifier: EsTreeNode) =>\n specifier.type === \"ImportSpecifier\" && specifier.imported?.name === \"motion\",\n );\n\n if (hasFullMotionImport) {\n context.report({\n node,\n message: 'Import \"m\" with LazyMotion instead of \"motion\" — saves ~30kb in bundle size',\n });\n }\n },\n }),\n};\n\nexport const noUndeferredThirdParty: Rule = {\n create: (context: RuleContext) => ({\n JSXOpeningElement(node: EsTreeNode) {\n if (node.name?.type !== \"JSXIdentifier\" || node.name.name !== \"script\") return;\n const attributes = node.attributes ?? [];\n if (!findJsxAttribute(attributes, \"src\")) return;\n\n if (!hasJsxAttribute(attributes, \"defer\") && !hasJsxAttribute(attributes, \"async\")) {\n context.report({\n node,\n message:\n \"Synchronous <script> with src — add defer or async to avoid blocking first paint\",\n });\n }\n },\n }),\n};\n","import { PASSIVE_EVENT_NAMES } from \"../constants.js\";\nimport { isMemberProperty } from \"../helpers.js\";\nimport type { EsTreeNode, Rule, RuleContext } from \"../types.js\";\n\nexport const clientPassiveEventListeners: Rule = {\n create: (context: RuleContext) => ({\n CallExpression(node: EsTreeNode) {\n if (!isMemberProperty(node.callee, \"addEventListener\")) return;\n if (node.arguments?.length < 2) return;\n\n const eventNameNode = node.arguments[0];\n if (eventNameNode.type !== \"Literal\" || !PASSIVE_EVENT_NAMES.has(eventNameNode.value)) return;\n\n const eventName = eventNameNode.value;\n const optionsArgument = node.arguments[2];\n\n if (!optionsArgument) {\n context.report({\n node,\n message: `\"${eventName}\" listener without { passive: true } — blocks scrolling performance`,\n });\n return;\n }\n\n if (optionsArgument.type !== \"ObjectExpression\") return;\n\n const hasPassiveTrue = optionsArgument.properties?.some(\n (property: EsTreeNode) =>\n property.type === \"Property\" &&\n property.key?.type === \"Identifier\" &&\n property.key.name === \"passive\" &&\n property.value?.type === \"Literal\" &&\n property.value.value === true,\n );\n\n if (!hasPassiveTrue) {\n context.report({\n node,\n message: `\"${eventName}\" listener without { passive: true } — blocks scrolling performance`,\n });\n }\n },\n }),\n};\n","import { INDEX_PARAMETER_NAMES } from \"../constants.js\";\nimport { findJsxAttribute, walkAst } from \"../helpers.js\";\nimport type { EsTreeNode, Rule, RuleContext } from \"../types.js\";\n\nconst extractIndexName = (node: EsTreeNode): string | null => {\n if (node.type === \"Identifier\" && INDEX_PARAMETER_NAMES.has(node.name)) return node.name;\n\n if (node.type === \"TemplateLiteral\") {\n const indexExpression = node.expressions?.find(\n (expression: EsTreeNode) =>\n expression.type === \"Identifier\" && INDEX_PARAMETER_NAMES.has(expression.name),\n );\n if (indexExpression) return indexExpression.name;\n }\n\n if (\n node.type === \"CallExpression\" &&\n node.callee?.type === \"MemberExpression\" &&\n node.callee.object?.type === \"Identifier\" &&\n INDEX_PARAMETER_NAMES.has(node.callee.object.name) &&\n node.callee.property?.type === \"Identifier\" &&\n node.callee.property.name === \"toString\"\n )\n return node.callee.object.name;\n\n if (\n node.type === \"CallExpression\" &&\n node.callee?.type === \"Identifier\" &&\n node.callee.name === \"String\" &&\n node.arguments?.[0]?.type === \"Identifier\" &&\n INDEX_PARAMETER_NAMES.has(node.arguments[0].name)\n )\n return node.arguments[0].name;\n\n return null;\n};\n\nconst isInsideStaticPlaceholderMap = (node: EsTreeNode): boolean => {\n let current = node;\n while (current.parent) {\n current = current.parent;\n if (\n current.type === \"CallExpression\" &&\n current.callee?.type === \"MemberExpression\" &&\n current.callee.property?.name === \"map\"\n ) {\n const receiver = current.callee.object;\n if (receiver?.type === \"CallExpression\") {\n const callee = receiver.callee;\n if (\n callee?.type === \"MemberExpression\" &&\n callee.object?.type === \"Identifier\" &&\n callee.object.name === \"Array\" &&\n callee.property?.name === \"from\"\n )\n return true;\n }\n if (\n receiver?.type === \"NewExpression\" &&\n receiver.callee?.type === \"Identifier\" &&\n receiver.callee.name === \"Array\"\n )\n return true;\n }\n }\n return false;\n};\n\nexport const noArrayIndexAsKey: Rule = {\n create: (context: RuleContext) => ({\n JSXAttribute(node: EsTreeNode) {\n if (node.name?.type !== \"JSXIdentifier\" || node.name.name !== \"key\") return;\n if (!node.value || node.value.type !== \"JSXExpressionContainer\") return;\n\n const indexName = extractIndexName(node.value.expression);\n if (!indexName) return;\n if (isInsideStaticPlaceholderMap(node)) return;\n\n context.report({\n node,\n message: `Array index \"${indexName}\" used as key — causes bugs when list is reordered or filtered`,\n });\n },\n }),\n};\n\nconst PREVENT_DEFAULT_ELEMENTS: Record<string, string> = {\n form: \"onSubmit\",\n a: \"onClick\",\n};\n\nconst containsPreventDefaultCall = (node: EsTreeNode): boolean => {\n let didFindPreventDefault = false;\n walkAst(node, (child) => {\n if (didFindPreventDefault) return;\n if (\n child.type === \"CallExpression\" &&\n child.callee?.type === \"MemberExpression\" &&\n child.callee.property?.type === \"Identifier\" &&\n child.callee.property.name === \"preventDefault\"\n ) {\n didFindPreventDefault = true;\n }\n });\n return didFindPreventDefault;\n};\n\nexport const noPreventDefault: Rule = {\n create: (context: RuleContext) => ({\n JSXOpeningElement(node: EsTreeNode) {\n const elementName = node.name?.type === \"JSXIdentifier\" ? node.name.name : null;\n if (!elementName) return;\n\n const targetEventProp = PREVENT_DEFAULT_ELEMENTS[elementName];\n if (!targetEventProp) return;\n\n const eventAttribute = findJsxAttribute(node.attributes ?? [], targetEventProp);\n if (!eventAttribute?.value || eventAttribute.value.type !== \"JSXExpressionContainer\") return;\n\n const expression = eventAttribute.value.expression;\n if (\n expression?.type !== \"ArrowFunctionExpression\" &&\n expression?.type !== \"FunctionExpression\"\n )\n return;\n\n if (!containsPreventDefaultCall(expression)) return;\n\n const message =\n elementName === \"form\"\n ? \"preventDefault() on <form> onSubmit — form won't work without JavaScript. Consider using a server action for progressive enhancement\"\n : \"preventDefault() on <a> onClick — use a <button> or routing component instead\";\n\n context.report({ node, message });\n },\n }),\n};\n\nexport const renderingConditionalRender: Rule = {\n create: (context: RuleContext) => ({\n LogicalExpression(node: EsTreeNode) {\n if (node.operator !== \"&&\") return;\n\n const isRightJsx = node.right?.type === \"JSXElement\" || node.right?.type === \"JSXFragment\";\n if (!isRightJsx) return;\n\n if (\n node.left?.type === \"MemberExpression\" &&\n node.left.property?.type === \"Identifier\" &&\n node.left.property.name === \"length\"\n ) {\n context.report({\n node,\n message:\n \"Conditional rendering with .length can render '0' — use .length > 0 or Boolean(.length)\",\n });\n }\n },\n }),\n};\n","import {\n CHAINABLE_ITERATION_METHODS,\n DEEP_NESTING_THRESHOLD,\n DUPLICATE_STORAGE_READ_THRESHOLD,\n SEQUENTIAL_AWAIT_THRESHOLD,\n STORAGE_OBJECTS,\n TEST_FILE_PATTERN,\n} from \"../constants.js\";\nimport { createLoopAwareVisitors, isMemberProperty, walkAst } from \"../helpers.js\";\nimport type { EsTreeNode, Rule, RuleContext } from \"../types.js\";\n\nexport const jsCombineIterations: Rule = {\n create: (context: RuleContext) => ({\n CallExpression(node: EsTreeNode) {\n if (node.callee?.type !== \"MemberExpression\" || node.callee.property?.type !== \"Identifier\")\n return;\n\n const outerMethod = node.callee.property.name;\n if (!CHAINABLE_ITERATION_METHODS.has(outerMethod)) return;\n\n const innerCall = node.callee.object;\n if (\n innerCall?.type !== \"CallExpression\" ||\n innerCall.callee?.type !== \"MemberExpression\" ||\n innerCall.callee.property?.type !== \"Identifier\"\n )\n return;\n\n const innerMethod = innerCall.callee.property.name;\n if (!CHAINABLE_ITERATION_METHODS.has(innerMethod)) return;\n\n context.report({\n node,\n message: `.${innerMethod}().${outerMethod}() iterates the array twice — combine into a single loop with .reduce() or for...of`,\n });\n },\n }),\n};\n\nexport const jsTosortedImmutable: Rule = {\n create: (context: RuleContext) => ({\n CallExpression(node: EsTreeNode) {\n if (!isMemberProperty(node.callee, \"sort\")) return;\n\n const receiver = node.callee.object;\n if (\n receiver?.type === \"ArrayExpression\" &&\n receiver.elements?.length === 1 &&\n receiver.elements[0]?.type === \"SpreadElement\"\n ) {\n context.report({\n node,\n message: \"[...array].sort() — use array.toSorted() for immutable sorting (ES2023)\",\n });\n }\n },\n }),\n};\n\nexport const jsHoistRegexp: Rule = {\n create: (context: RuleContext) =>\n createLoopAwareVisitors({\n NewExpression(node: EsTreeNode) {\n if (node.callee?.type === \"Identifier\" && node.callee.name === \"RegExp\") {\n context.report({\n node,\n message: \"new RegExp() inside a loop — hoist to a module-level constant\",\n });\n }\n },\n }),\n};\n\nexport const jsMinMaxLoop: Rule = {\n create: (context: RuleContext) => ({\n MemberExpression(node: EsTreeNode) {\n if (!node.computed) return;\n\n const object = node.object;\n if (object?.type !== \"CallExpression\" || !isMemberProperty(object.callee, \"sort\")) return;\n\n const isFirstElement = node.property?.type === \"Literal\" && node.property.value === 0;\n const isLastElement =\n node.property?.type === \"BinaryExpression\" &&\n node.property.operator === \"-\" &&\n node.property.right?.type === \"Literal\" &&\n node.property.right.value === 1;\n\n if (isFirstElement || isLastElement) {\n const targetFunction = isFirstElement ? \"min\" : \"max\";\n context.report({\n node,\n message: `array.sort()[${isFirstElement ? \"0\" : \"length-1\"}] for min/max — use Math.${targetFunction}(...array) instead (O(n) vs O(n log n))`,\n });\n }\n },\n }),\n};\n\nexport const jsSetMapLookups: Rule = {\n create: (context: RuleContext) =>\n createLoopAwareVisitors({\n CallExpression(node: EsTreeNode) {\n if (node.callee?.type !== \"MemberExpression\" || node.callee.property?.type !== \"Identifier\")\n return;\n const methodName = node.callee.property.name;\n if (methodName === \"includes\" || methodName === \"indexOf\") {\n context.report({\n node,\n message: `array.${methodName}() in a loop is O(n) per call — convert to a Set for O(1) lookups`,\n });\n }\n },\n }),\n};\n\nexport const jsBatchDomCss: Rule = {\n create: (context: RuleContext) => {\n const isStyleAssignment = (node: EsTreeNode): boolean =>\n node.type === \"ExpressionStatement\" &&\n node.expression?.type === \"AssignmentExpression\" &&\n node.expression.left?.type === \"MemberExpression\" &&\n node.expression.left.object?.type === \"MemberExpression\" &&\n node.expression.left.object.property?.type === \"Identifier\" &&\n node.expression.left.object.property.name === \"style\";\n\n return {\n BlockStatement(node: EsTreeNode) {\n const statements = node.body ?? [];\n for (let statementIndex = 1; statementIndex < statements.length; statementIndex++) {\n if (\n isStyleAssignment(statements[statementIndex]) &&\n isStyleAssignment(statements[statementIndex - 1])\n ) {\n context.report({\n node: statements[statementIndex],\n message:\n \"Multiple sequential element.style assignments — batch with cssText or classList for fewer reflows\",\n });\n }\n }\n },\n };\n },\n};\n\nexport const jsIndexMaps: Rule = {\n create: (context: RuleContext) =>\n createLoopAwareVisitors({\n CallExpression(node: EsTreeNode) {\n if (node.callee?.type !== \"MemberExpression\" || node.callee.property?.type !== \"Identifier\")\n return;\n const methodName = node.callee.property.name;\n if (methodName === \"find\" || methodName === \"findIndex\") {\n context.report({\n node,\n message: `array.${methodName}() in a loop is O(n*m) — build a Map for O(1) lookups`,\n });\n }\n },\n }),\n};\n\nexport const jsCacheStorage: Rule = {\n create: (context: RuleContext) => {\n const storageReadCounts = new Map<string, number>();\n\n return {\n CallExpression(node: EsTreeNode) {\n if (!isMemberProperty(node.callee, \"getItem\")) return;\n if (\n node.callee.object?.type !== \"Identifier\" ||\n !STORAGE_OBJECTS.has(node.callee.object.name)\n )\n return;\n if (node.arguments?.[0]?.type !== \"Literal\") return;\n\n const storageKey = String(node.arguments[0].value);\n const readCount = (storageReadCounts.get(storageKey) ?? 0) + 1;\n storageReadCounts.set(storageKey, readCount);\n\n if (readCount === DUPLICATE_STORAGE_READ_THRESHOLD) {\n const storageName = node.callee.object.name;\n context.report({\n node,\n message: `${storageName}.getItem(\"${storageKey}\") called multiple times — cache the result in a variable`,\n });\n }\n },\n };\n },\n};\n\nexport const jsEarlyExit: Rule = {\n create: (context: RuleContext) => ({\n IfStatement(node: EsTreeNode) {\n if (node.consequent?.type !== \"BlockStatement\" || !node.consequent.body) return;\n\n let nestingDepth = 0;\n let currentBlock = node.consequent;\n while (currentBlock?.type === \"BlockStatement\" && currentBlock.body?.length === 1) {\n const innerStatement = currentBlock.body[0];\n if (innerStatement.type !== \"IfStatement\") break;\n nestingDepth++;\n currentBlock = innerStatement.consequent;\n }\n\n if (nestingDepth >= DEEP_NESTING_THRESHOLD) {\n context.report({\n node,\n message: `${nestingDepth + 1} levels of nested if statements — use early returns to flatten`,\n });\n }\n },\n }),\n};\n\nexport const asyncParallel: Rule = {\n create: (context: RuleContext) => {\n const filename = context.getFilename?.() ?? \"\";\n const isTestFile = TEST_FILE_PATTERN.test(filename);\n\n return {\n BlockStatement(node: EsTreeNode) {\n if (isTestFile) return;\n const consecutiveAwaitStatements: EsTreeNode[] = [];\n\n const flushConsecutiveAwaits = (): void => {\n if (consecutiveAwaitStatements.length >= SEQUENTIAL_AWAIT_THRESHOLD) {\n reportIfIndependent(consecutiveAwaitStatements, context);\n }\n consecutiveAwaitStatements.length = 0;\n };\n\n for (const statement of node.body ?? []) {\n const isAwaitStatement =\n (statement.type === \"VariableDeclaration\" &&\n statement.declarations?.length === 1 &&\n statement.declarations[0].init?.type === \"AwaitExpression\") ||\n (statement.type === \"ExpressionStatement\" &&\n statement.expression?.type === \"AwaitExpression\");\n\n if (isAwaitStatement) {\n consecutiveAwaitStatements.push(statement);\n } else {\n flushConsecutiveAwaits();\n }\n }\n flushConsecutiveAwaits();\n },\n };\n },\n};\n\nconst reportIfIndependent = (statements: EsTreeNode[], context: RuleContext): void => {\n const declaredNames = new Set<string>();\n\n for (const statement of statements) {\n if (statement.type !== \"VariableDeclaration\") continue;\n const declarator = statement.declarations[0];\n const awaitArgument = declarator.init?.argument;\n\n let referencesEarlierResult = false;\n walkAst(awaitArgument, (child: EsTreeNode) => {\n if (child.type === \"Identifier\" && declaredNames.has(child.name)) {\n referencesEarlierResult = true;\n }\n });\n\n if (referencesEarlierResult) return;\n\n if (declarator.id?.type === \"Identifier\") {\n declaredNames.add(declarator.id.name);\n }\n }\n\n context.report({\n node: statements[0],\n message: `${statements.length} sequential await statements that appear independent — use Promise.all() for parallel execution`,\n });\n};\n","import {\n APP_DIRECTORY_PATTERN,\n EFFECT_HOOK_NAMES,\n EXECUTABLE_SCRIPT_TYPES,\n GOOGLE_FONTS_PATTERN,\n INTERNAL_PAGE_PATH_PATTERN,\n MUTATING_ROUTE_SEGMENTS,\n NEXTJS_NAVIGATION_FUNCTIONS,\n OG_ROUTE_PATTERN,\n PAGE_FILE_PATTERN,\n PAGE_OR_LAYOUT_FILE_PATTERN,\n PAGES_DIRECTORY_PATTERN,\n POLYFILL_SCRIPT_PATTERN,\n ROUTE_HANDLER_FILE_PATTERN,\n} from \"../constants.js\";\nimport {\n containsFetchCall,\n findJsxAttribute,\n findSideEffect,\n getEffectCallback,\n hasDirective,\n hasJsxAttribute,\n isComponentAssignment,\n isHookCall,\n isMemberProperty,\n isUppercaseName,\n walkAst,\n} from \"../helpers.js\";\nimport type { EsTreeNode, Rule, RuleContext } from \"../types.js\";\n\nexport const nextjsNoImgElement: Rule = {\n create: (context: RuleContext) => {\n const filename = context.getFilename?.() ?? \"\";\n const isOgRoute = OG_ROUTE_PATTERN.test(filename);\n\n return {\n JSXOpeningElement(node: EsTreeNode) {\n if (isOgRoute) return;\n if (node.name?.type === \"JSXIdentifier\" && node.name.name === \"img\") {\n context.report({\n node,\n message:\n \"Use next/image instead of <img> — provides automatic optimization, lazy loading, and responsive srcset\",\n });\n }\n },\n };\n },\n};\n\nexport const nextjsAsyncClientComponent: Rule = {\n create: (context: RuleContext) => {\n let fileHasUseClient = false;\n\n return {\n Program(programNode: EsTreeNode) {\n fileHasUseClient = hasDirective(programNode, \"use client\");\n },\n FunctionDeclaration(node: EsTreeNode) {\n if (!fileHasUseClient || !node.async) return;\n if (!node.id?.name || !isUppercaseName(node.id.name)) return;\n context.report({\n node,\n message: `Async client component \"${node.id.name}\" — client components cannot be async`,\n });\n },\n VariableDeclarator(node: EsTreeNode) {\n if (!fileHasUseClient) return;\n if (!isComponentAssignment(node) || !node.init?.async) return;\n context.report({\n node,\n message: `Async client component \"${node.id.name}\" — client components cannot be async`,\n });\n },\n };\n },\n};\n\nexport const nextjsNoAElement: Rule = {\n create: (context: RuleContext) => ({\n JSXOpeningElement(node: EsTreeNode) {\n if (node.name?.type !== \"JSXIdentifier\" || node.name.name !== \"a\") return;\n\n const hrefAttribute = findJsxAttribute(node.attributes ?? [], \"href\");\n if (!hrefAttribute?.value) return;\n\n let hrefValue = null;\n if (hrefAttribute.value.type === \"Literal\") {\n hrefValue = hrefAttribute.value.value;\n } else if (\n hrefAttribute.value.type === \"JSXExpressionContainer\" &&\n hrefAttribute.value.expression?.type === \"Literal\"\n ) {\n hrefValue = hrefAttribute.value.expression.value;\n }\n\n if (typeof hrefValue === \"string\" && hrefValue.startsWith(\"/\")) {\n context.report({\n node,\n message:\n \"Use next/link instead of <a> for internal links — enables client-side navigation and prefetching\",\n });\n }\n },\n }),\n};\n\nexport const nextjsNoUseSearchParamsWithoutSuspense: Rule = {\n create: (context: RuleContext) => ({\n CallExpression(node: EsTreeNode) {\n if (!isHookCall(node, \"useSearchParams\")) return;\n context.report({\n node,\n message:\n \"useSearchParams() requires a <Suspense> boundary — without one, the entire page bails out to client-side rendering\",\n });\n },\n }),\n};\n\nexport const nextjsNoClientFetchForServerData: Rule = {\n create: (context: RuleContext) => {\n let fileHasUseClient = false;\n\n return {\n Program(programNode: EsTreeNode) {\n fileHasUseClient = hasDirective(programNode, \"use client\");\n },\n CallExpression(node: EsTreeNode) {\n if (!fileHasUseClient || !isHookCall(node, EFFECT_HOOK_NAMES)) return;\n\n const callback = getEffectCallback(node);\n if (!callback || !containsFetchCall(callback)) return;\n\n const filename = context.getFilename?.() ?? \"\";\n const isPageOrLayoutFile =\n PAGE_OR_LAYOUT_FILE_PATTERN.test(filename) || PAGES_DIRECTORY_PATTERN.test(filename);\n\n if (isPageOrLayoutFile) {\n context.report({\n node,\n message:\n \"useEffect + fetch in a page/layout — fetch data server-side with a server component instead\",\n });\n }\n },\n };\n },\n};\n\nexport const nextjsMissingMetadata: Rule = {\n create: (context: RuleContext) => ({\n Program(programNode: EsTreeNode) {\n const filename = context.getFilename?.() ?? \"\";\n if (!PAGE_FILE_PATTERN.test(filename)) return;\n if (INTERNAL_PAGE_PATH_PATTERN.test(filename)) return;\n\n const hasMetadataExport = programNode.body?.some((statement: EsTreeNode) => {\n if (statement.type !== \"ExportNamedDeclaration\") return false;\n const declaration = statement.declaration;\n if (declaration?.type === \"VariableDeclaration\") {\n return declaration.declarations?.some(\n (declarator: EsTreeNode) =>\n declarator.id?.type === \"Identifier\" &&\n (declarator.id.name === \"metadata\" || declarator.id.name === \"generateMetadata\"),\n );\n }\n if (declaration?.type === \"FunctionDeclaration\") {\n return declaration.id?.name === \"generateMetadata\";\n }\n return false;\n });\n\n if (!hasMetadataExport) {\n context.report({\n node: programNode,\n message: \"Page without metadata or generateMetadata export — hurts SEO\",\n });\n }\n },\n }),\n};\n\nconst describeClientSideNavigation = (node: EsTreeNode): string | null => {\n if (node.type === \"CallExpression\" && node.callee?.type === \"MemberExpression\") {\n const objectName = node.callee.object?.type === \"Identifier\" ? node.callee.object.name : null;\n const methodName =\n node.callee.property?.type === \"Identifier\" ? node.callee.property.name : null;\n if (objectName === \"router\" && (methodName === \"push\" || methodName === \"replace\")) {\n return `router.${methodName}() in useEffect — use redirect() from next/navigation or handle navigation in an event handler`;\n }\n }\n\n if (node.type === \"AssignmentExpression\" && node.left?.type === \"MemberExpression\") {\n const objectName = node.left.object?.type === \"Identifier\" ? node.left.object.name : null;\n const propertyName = node.left.property?.type === \"Identifier\" ? node.left.property.name : null;\n if (objectName === \"window\" && propertyName === \"location\") {\n return \"window.location assignment in useEffect — use redirect() from next/navigation or handle in middleware instead\";\n }\n if (objectName === \"location\" && propertyName === \"href\") {\n return \"location.href assignment in useEffect — use redirect() from next/navigation or handle in middleware instead\";\n }\n }\n\n return null;\n};\n\nexport const nextjsNoClientSideRedirect: Rule = {\n create: (context: RuleContext) => ({\n CallExpression(node: EsTreeNode) {\n if (!isHookCall(node, EFFECT_HOOK_NAMES)) return;\n const callback = getEffectCallback(node);\n if (!callback) return;\n\n walkAst(callback, (child: EsTreeNode) => {\n const navigationDescription = describeClientSideNavigation(child);\n if (navigationDescription) {\n context.report({\n node: child,\n message: navigationDescription,\n });\n }\n });\n },\n }),\n};\n\nexport const nextjsNoRedirectInTryCatch: Rule = {\n create: (context: RuleContext) => {\n let tryCatchDepth = 0;\n\n return {\n TryStatement() {\n tryCatchDepth++;\n },\n \"TryStatement:exit\"() {\n tryCatchDepth--;\n },\n CallExpression(node: EsTreeNode) {\n if (tryCatchDepth === 0) return;\n if (node.callee?.type !== \"Identifier\") return;\n if (!NEXTJS_NAVIGATION_FUNCTIONS.has(node.callee.name)) return;\n\n context.report({\n node,\n message: `${node.callee.name}() inside try-catch — this throws a special error Next.js handles internally. Move it outside the try block or use unstable_rethrow() in the catch`,\n });\n },\n };\n },\n};\n\nexport const nextjsImageMissingSizes: Rule = {\n create: (context: RuleContext) => ({\n JSXOpeningElement(node: EsTreeNode) {\n if (node.name?.type !== \"JSXIdentifier\" || node.name.name !== \"Image\") return;\n const attributes = node.attributes ?? [];\n if (!hasJsxAttribute(attributes, \"fill\")) return;\n if (hasJsxAttribute(attributes, \"sizes\")) return;\n\n context.report({\n node,\n message:\n \"next/image with fill but no sizes — the browser downloads the largest image. Add a sizes attribute for responsive behavior\",\n });\n },\n }),\n};\n\nexport const nextjsNoNativeScript: Rule = {\n create: (context: RuleContext) => ({\n JSXOpeningElement(node: EsTreeNode) {\n if (node.name?.type !== \"JSXIdentifier\" || node.name.name !== \"script\") return;\n\n const typeAttribute = findJsxAttribute(node.attributes ?? [], \"type\");\n const typeValue = typeAttribute?.value?.type === \"Literal\" ? typeAttribute.value.value : null;\n if (typeof typeValue === \"string\" && !EXECUTABLE_SCRIPT_TYPES.has(typeValue)) return;\n\n context.report({\n node,\n message:\n \"Use next/script <Script> instead of <script> — provides loading strategy optimization and deferred loading\",\n });\n },\n }),\n};\n\nexport const nextjsInlineScriptMissingId: Rule = {\n create: (context: RuleContext) => ({\n JSXOpeningElement(node: EsTreeNode) {\n if (node.name?.type !== \"JSXIdentifier\" || node.name.name !== \"Script\") return;\n const attributes = node.attributes ?? [];\n\n if (hasJsxAttribute(attributes, \"src\")) return;\n if (hasJsxAttribute(attributes, \"id\")) return;\n\n context.report({\n node,\n message:\n \"Inline <Script> without id — Next.js requires an id attribute to track inline scripts\",\n });\n },\n }),\n};\n\nexport const nextjsNoFontLink: Rule = {\n create: (context: RuleContext) => ({\n JSXOpeningElement(node: EsTreeNode) {\n if (node.name?.type !== \"JSXIdentifier\" || node.name.name !== \"link\") return;\n const attributes = node.attributes ?? [];\n\n const hrefAttribute = findJsxAttribute(attributes, \"href\");\n if (!hrefAttribute?.value) return;\n\n const hrefValue = hrefAttribute.value.type === \"Literal\" ? hrefAttribute.value.value : null;\n\n if (typeof hrefValue === \"string\" && GOOGLE_FONTS_PATTERN.test(hrefValue)) {\n context.report({\n node,\n message:\n \"Loading Google Fonts via <link> — use next/font instead for self-hosting, zero layout shift, and no render-blocking requests\",\n });\n }\n },\n }),\n};\n\nexport const nextjsNoCssLink: Rule = {\n create: (context: RuleContext) => ({\n JSXOpeningElement(node: EsTreeNode) {\n if (node.name?.type !== \"JSXIdentifier\" || node.name.name !== \"link\") return;\n const attributes = node.attributes ?? [];\n\n const relAttribute = findJsxAttribute(attributes, \"rel\");\n if (!relAttribute?.value) return;\n const relValue = relAttribute.value.type === \"Literal\" ? relAttribute.value.value : null;\n if (relValue !== \"stylesheet\") return;\n\n const hrefAttribute = findJsxAttribute(attributes, \"href\");\n if (!hrefAttribute?.value) return;\n const hrefValue = hrefAttribute.value.type === \"Literal\" ? hrefAttribute.value.value : null;\n if (typeof hrefValue === \"string\" && GOOGLE_FONTS_PATTERN.test(hrefValue)) return;\n\n context.report({\n node,\n message: '<link rel=\"stylesheet\"> tag — import CSS directly for bundling and optimization',\n });\n },\n }),\n};\n\nexport const nextjsNoPolyfillScript: Rule = {\n create: (context: RuleContext) => ({\n JSXOpeningElement(node: EsTreeNode) {\n if (node.name?.type !== \"JSXIdentifier\") return;\n if (node.name.name !== \"script\" && node.name.name !== \"Script\") return;\n\n const srcAttribute = findJsxAttribute(node.attributes ?? [], \"src\");\n if (!srcAttribute?.value) return;\n\n const srcValue = srcAttribute.value.type === \"Literal\" ? srcAttribute.value.value : null;\n\n if (typeof srcValue === \"string\" && POLYFILL_SCRIPT_PATTERN.test(srcValue)) {\n context.report({\n node,\n message:\n \"Polyfill CDN script — Next.js includes polyfills for fetch, Promise, Object.assign, and 50+ others automatically\",\n });\n }\n },\n }),\n};\n\nexport const nextjsNoHeadImport: Rule = {\n create: (context: RuleContext) => ({\n ImportDeclaration(node: EsTreeNode) {\n if (node.source?.value !== \"next/head\") return;\n\n const filename = context.getFilename?.() ?? \"\";\n if (!APP_DIRECTORY_PATTERN.test(filename)) return;\n\n context.report({\n node,\n message: \"next/head is not supported in the App Router — use the Metadata API instead\",\n });\n },\n }),\n};\n\nconst extractMutatingRouteSegment = (filename: string): string | null => {\n const segments = filename.split(\"/\");\n for (const segment of segments) {\n const cleaned = segment.replace(/^\\[.*\\]$/, \"\");\n if (MUTATING_ROUTE_SEGMENTS.has(cleaned)) return cleaned;\n }\n return null;\n};\n\nconst getExportedGetHandlerBody = (node: EsTreeNode): EsTreeNode | null => {\n if (node.type !== \"ExportNamedDeclaration\") return null;\n const declaration = node.declaration;\n if (!declaration) return null;\n\n if (declaration.type === \"FunctionDeclaration\" && declaration.id?.name === \"GET\") {\n return declaration.body;\n }\n\n if (declaration.type === \"VariableDeclaration\") {\n const declarator = declaration.declarations?.[0];\n if (\n declarator?.id?.type === \"Identifier\" &&\n declarator.id.name === \"GET\" &&\n declarator.init &&\n (declarator.init.type === \"ArrowFunctionExpression\" ||\n declarator.init.type === \"FunctionExpression\")\n ) {\n return declarator.init.body;\n }\n }\n\n return null;\n};\n\nexport const nextjsNoSideEffectInGetHandler: Rule = {\n create: (context: RuleContext) => ({\n ExportNamedDeclaration(node: EsTreeNode) {\n const filename = context.getFilename?.() ?? \"\";\n if (!ROUTE_HANDLER_FILE_PATTERN.test(filename)) return;\n\n const handlerBody = getExportedGetHandlerBody(node);\n if (!handlerBody) return;\n\n const mutatingSegment = extractMutatingRouteSegment(filename);\n if (mutatingSegment) {\n context.report({\n node,\n message: `GET handler on \"/${mutatingSegment}\" route — use POST to prevent CSRF and unintended prefetch triggers`,\n });\n return;\n }\n\n const sideEffect = findSideEffect(handlerBody);\n if (sideEffect) {\n context.report({\n node,\n message: `GET handler has side effects (${sideEffect}) — use POST to prevent CSRF and unintended prefetch triggers`,\n });\n }\n },\n }),\n};\n","import {\n ANIMATION_CALLBACK_NAMES,\n BLUR_VALUE_PATTERN,\n EFFECT_HOOK_NAMES,\n LARGE_BLUR_THRESHOLD_PX,\n LAYOUT_PROPERTIES,\n LOADING_STATE_PATTERN,\n MOTION_ANIMATE_PROPS,\n SETTER_PATTERN,\n} from \"../constants.js\";\nimport {\n getEffectCallback,\n isComponentAssignment,\n isHookCall,\n isMemberProperty,\n isSimpleExpression,\n isUppercaseName,\n walkAst,\n} from \"../helpers.js\";\nimport type { EsTreeNode, Rule, RuleContext } from \"../types.js\";\n\nconst isMemoCall = (node: EsTreeNode): boolean => {\n if (node.type !== \"CallExpression\") return false;\n if (node.callee?.type === \"Identifier\" && node.callee.name === \"memo\") return true;\n if (\n node.callee?.type === \"MemberExpression\" &&\n node.callee.object?.type === \"Identifier\" &&\n node.callee.object.name === \"React\" &&\n node.callee.property?.type === \"Identifier\" &&\n node.callee.property.name === \"memo\"\n )\n return true;\n return false;\n};\n\nconst isInlineReference = (node: EsTreeNode): string | null => {\n if (\n node.type === \"ArrowFunctionExpression\" ||\n node.type === \"FunctionExpression\" ||\n (node.type === \"CallExpression\" &&\n node.callee?.type === \"MemberExpression\" &&\n node.callee.property?.name === \"bind\")\n )\n return \"functions\";\n\n if (node.type === \"ObjectExpression\") return \"objects\";\n if (node.type === \"ArrayExpression\") return \"Arrays\";\n if (node.type === \"JSXElement\" || node.type === \"JSXFragment\") return \"JSX\";\n\n return null;\n};\n\nexport const noInlinePropOnMemoComponent: Rule = {\n create: (context: RuleContext) => {\n const memoizedComponentNames = new Set<string>();\n\n return {\n VariableDeclarator(node: EsTreeNode) {\n if (node.id?.type !== \"Identifier\" || !node.init) return;\n if (isMemoCall(node.init)) {\n memoizedComponentNames.add(node.id.name);\n }\n },\n ExportDefaultDeclaration(node: EsTreeNode) {\n if (node.declaration && isMemoCall(node.declaration)) {\n const innerArgument = node.declaration.arguments?.[0];\n if (innerArgument?.type === \"Identifier\") {\n memoizedComponentNames.add(innerArgument.name);\n }\n }\n },\n JSXAttribute(node: EsTreeNode) {\n if (!node.value || node.value.type !== \"JSXExpressionContainer\") return;\n\n const openingElement = node.parent;\n if (!openingElement || openingElement.type !== \"JSXOpeningElement\") return;\n\n let elementName: string | null = null;\n if (openingElement.name?.type === \"JSXIdentifier\") {\n elementName = openingElement.name.name;\n }\n if (!elementName || !memoizedComponentNames.has(elementName)) return;\n\n const propType = isInlineReference(node.value.expression);\n if (propType) {\n context.report({\n node: node.value.expression,\n message: `JSX attribute values should not contain ${propType} created in the same scope — ${elementName} is wrapped in memo(), so new references cause unnecessary re-renders`,\n });\n }\n },\n };\n },\n};\n\nexport const noUsememoSimpleExpression: Rule = {\n create: (context: RuleContext) => ({\n CallExpression(node: EsTreeNode) {\n if (!isHookCall(node, \"useMemo\")) return;\n\n const callback = node.arguments?.[0];\n if (!callback) return;\n if (callback.type !== \"ArrowFunctionExpression\" && callback.type !== \"FunctionExpression\")\n return;\n\n let returnExpression = null;\n if (callback.body?.type !== \"BlockStatement\") {\n returnExpression = callback.body;\n } else if (\n callback.body.body?.length === 1 &&\n callback.body.body[0].type === \"ReturnStatement\"\n ) {\n returnExpression = callback.body.body[0].argument;\n }\n\n if (returnExpression && isSimpleExpression(returnExpression)) {\n context.report({\n node,\n message:\n \"useMemo wrapping a trivially cheap expression — memo overhead exceeds the computation\",\n });\n }\n },\n }),\n};\n\nconst isMotionElement = (attributeNode: EsTreeNode): boolean => {\n const openingElement = attributeNode.parent;\n if (!openingElement || openingElement.type !== \"JSXOpeningElement\") return false;\n\n const elementName = openingElement.name;\n if (\n elementName?.type === \"JSXMemberExpression\" &&\n elementName.object?.type === \"JSXIdentifier\" &&\n (elementName.object.name === \"motion\" || elementName.object.name === \"m\")\n )\n return true;\n\n if (elementName?.type === \"JSXIdentifier\" && elementName.name.startsWith(\"Motion\")) return true;\n\n return false;\n};\n\nexport const noLayoutPropertyAnimation: Rule = {\n create: (context: RuleContext) => ({\n JSXAttribute(node: EsTreeNode) {\n if (node.name?.type !== \"JSXIdentifier\" || !MOTION_ANIMATE_PROPS.has(node.name.name)) return;\n if (!node.value || node.value.type !== \"JSXExpressionContainer\") return;\n if (isMotionElement(node)) return;\n\n const expression = node.value.expression;\n if (expression?.type !== \"ObjectExpression\") return;\n\n for (const property of expression.properties ?? []) {\n if (property.type !== \"Property\") continue;\n let propertyName = null;\n if (property.key?.type === \"Identifier\") {\n propertyName = property.key.name;\n } else if (property.key?.type === \"Literal\") {\n propertyName = property.key.value;\n }\n\n if (propertyName && LAYOUT_PROPERTIES.has(propertyName)) {\n context.report({\n node: property,\n message: `Animating layout property \"${propertyName}\" triggers layout recalculation every frame — use transform/scale or the layout prop`,\n });\n }\n }\n },\n }),\n};\n\nexport const noTransitionAll: Rule = {\n create: (context: RuleContext) => ({\n JSXAttribute(node: EsTreeNode) {\n if (node.name?.type !== \"JSXIdentifier\" || node.name.name !== \"style\") return;\n if (node.value?.type !== \"JSXExpressionContainer\") return;\n\n const expression = node.value.expression;\n if (expression?.type !== \"ObjectExpression\") return;\n\n for (const property of expression.properties ?? []) {\n if (property.type !== \"Property\") continue;\n const key = property.key?.type === \"Identifier\" ? property.key.name : null;\n if (key !== \"transition\") continue;\n\n if (\n property.value?.type === \"Literal\" &&\n typeof property.value.value === \"string\" &&\n property.value.value.startsWith(\"all\")\n ) {\n context.report({\n node: property,\n message:\n 'transition: \"all\" animates every property including layout — list only the properties you animate',\n });\n }\n }\n },\n }),\n};\n\nexport const noGlobalCssVariableAnimation: Rule = {\n create: (context: RuleContext) => ({\n CallExpression(node: EsTreeNode) {\n if (node.callee?.type !== \"Identifier\") return;\n if (!ANIMATION_CALLBACK_NAMES.has(node.callee.name)) return;\n\n const callback = node.arguments?.[0];\n if (!callback) return;\n\n const calleeName = node.callee.name;\n walkAst(callback, (child: EsTreeNode) => {\n if (child.type !== \"CallExpression\") return;\n if (!isMemberProperty(child.callee, \"setProperty\")) return;\n if (child.arguments?.[0]?.type !== \"Literal\") return;\n\n const variableName = child.arguments[0].value;\n if (typeof variableName !== \"string\" || !variableName.startsWith(\"--\")) return;\n\n context.report({\n node: child,\n message: `CSS variable \"${variableName}\" updated in ${calleeName} — forces style recalculation on all inheriting elements every frame`,\n });\n });\n },\n }),\n};\n\nexport const noLargeAnimatedBlur: Rule = {\n create: (context: RuleContext) => ({\n JSXAttribute(node: EsTreeNode) {\n if (node.name?.type !== \"JSXIdentifier\") return;\n if (node.name.name !== \"style\" && !MOTION_ANIMATE_PROPS.has(node.name.name)) return;\n if (node.value?.type !== \"JSXExpressionContainer\") return;\n\n const expression = node.value.expression;\n if (expression?.type !== \"ObjectExpression\") return;\n\n for (const property of expression.properties ?? []) {\n if (property.type !== \"Property\") continue;\n const key = property.key?.type === \"Identifier\" ? property.key.name : null;\n if (key !== \"filter\" && key !== \"backdropFilter\" && key !== \"WebkitBackdropFilter\")\n continue;\n if (property.value?.type !== \"Literal\" || typeof property.value.value !== \"string\")\n continue;\n\n const match = BLUR_VALUE_PATTERN.exec(property.value.value);\n if (!match) continue;\n\n const blurRadius = Number.parseFloat(match[1]);\n if (blurRadius > LARGE_BLUR_THRESHOLD_PX) {\n context.report({\n node: property,\n message: `blur(${blurRadius}px) is expensive — cost escalates with radius and layer size, can exceed GPU memory on mobile`,\n });\n }\n }\n },\n }),\n};\n\nexport const noScaleFromZero: Rule = {\n create: (context: RuleContext) => ({\n JSXAttribute(node: EsTreeNode) {\n if (node.name?.type !== \"JSXIdentifier\") return;\n if (node.name.name !== \"initial\" && node.name.name !== \"exit\") return;\n if (node.value?.type !== \"JSXExpressionContainer\") return;\n\n const expression = node.value.expression;\n if (expression?.type !== \"ObjectExpression\") return;\n\n for (const property of expression.properties ?? []) {\n if (property.type !== \"Property\") continue;\n const key = property.key?.type === \"Identifier\" ? property.key.name : null;\n if (key !== \"scale\") continue;\n\n if (property.value?.type === \"Literal\" && property.value.value === 0) {\n context.report({\n node: property,\n message:\n \"scale: 0 makes elements appear from nowhere — use scale: 0.95 with opacity: 0 for natural entrance\",\n });\n }\n }\n },\n }),\n};\n\nexport const noPermanentWillChange: Rule = {\n create: (context: RuleContext) => ({\n JSXAttribute(node: EsTreeNode) {\n if (node.name?.type !== \"JSXIdentifier\" || node.name.name !== \"style\") return;\n if (node.value?.type !== \"JSXExpressionContainer\") return;\n\n const expression = node.value.expression;\n if (expression?.type !== \"ObjectExpression\") return;\n\n for (const property of expression.properties ?? []) {\n if (property.type !== \"Property\") continue;\n const key = property.key?.type === \"Identifier\" ? property.key.name : null;\n if (key !== \"willChange\") continue;\n\n context.report({\n node: property,\n message:\n \"Permanent will-change wastes GPU memory — apply only during active animation and remove after\",\n });\n }\n },\n }),\n};\n\nexport const rerenderMemoWithDefaultValue: Rule = {\n create: (context: RuleContext) => {\n const checkDefaultProps = (params: EsTreeNode[]): void => {\n for (const param of params) {\n if (param.type !== \"ObjectPattern\") continue;\n for (const property of param.properties ?? []) {\n if (property.type !== \"Property\" || property.value?.type !== \"AssignmentPattern\")\n continue;\n const defaultValue = property.value.right;\n if (defaultValue?.type === \"ObjectExpression\" && defaultValue.properties?.length === 0) {\n context.report({\n node: defaultValue,\n message:\n \"Default prop value {} creates a new object reference every render — extract to a module-level constant\",\n });\n }\n if (defaultValue?.type === \"ArrayExpression\" && defaultValue.elements?.length === 0) {\n context.report({\n node: defaultValue,\n message:\n \"Default prop value [] creates a new array reference every render — extract to a module-level constant\",\n });\n }\n }\n }\n };\n\n return {\n FunctionDeclaration(node: EsTreeNode) {\n if (!node.id?.name || !isUppercaseName(node.id.name)) return;\n checkDefaultProps(node.params ?? []);\n },\n VariableDeclarator(node: EsTreeNode) {\n if (!isComponentAssignment(node)) return;\n checkDefaultProps(node.init.params ?? []);\n },\n };\n },\n};\n\nexport const renderingAnimateSvgWrapper: Rule = {\n create: (context: RuleContext) => ({\n JSXOpeningElement(node: EsTreeNode) {\n if (node.name?.type !== \"JSXIdentifier\" || node.name.name !== \"svg\") return;\n\n const hasAnimationProp = node.attributes?.some(\n (attribute: EsTreeNode) =>\n attribute.type === \"JSXAttribute\" &&\n attribute.name?.type === \"JSXIdentifier\" &&\n MOTION_ANIMATE_PROPS.has(attribute.name.name),\n );\n\n if (hasAnimationProp) {\n context.report({\n node,\n message:\n \"Animation props directly on <svg> — wrap in a <div> or <motion.div> for better rendering performance\",\n });\n }\n },\n }),\n};\n\nexport const renderingUsetransitionLoading: Rule = {\n create: (context: RuleContext) => ({\n VariableDeclarator(node: EsTreeNode) {\n if (node.id?.type !== \"ArrayPattern\" || !node.id.elements?.length) return;\n if (!node.init || !isHookCall(node.init, \"useState\")) return;\n if (!node.init.arguments?.length) return;\n\n const initializer = node.init.arguments[0];\n if (initializer.type !== \"Literal\" || initializer.value !== false) return;\n\n const stateVariableName = node.id.elements[0]?.name;\n if (!stateVariableName || !LOADING_STATE_PATTERN.test(stateVariableName)) return;\n\n context.report({\n node: node.init,\n message: `useState for \"${stateVariableName}\" — if this guards a state transition (not an async fetch), consider useTransition instead`,\n });\n },\n }),\n};\n\nexport const renderingHydrationNoFlicker: Rule = {\n create: (context: RuleContext) => ({\n CallExpression(node: EsTreeNode) {\n if (!isHookCall(node, EFFECT_HOOK_NAMES) || node.arguments?.length < 2) return;\n\n const depsNode = node.arguments[1];\n if (depsNode.type !== \"ArrayExpression\" || depsNode.elements?.length !== 0) return;\n\n const callback = getEffectCallback(node);\n if (!callback) return;\n\n const bodyStatements =\n callback.body?.type === \"BlockStatement\" ? callback.body.body : [callback.body];\n if (!bodyStatements || bodyStatements.length !== 1) return;\n\n const soleStatement = bodyStatements[0];\n if (\n soleStatement?.type === \"ExpressionStatement\" &&\n soleStatement.expression?.type === \"CallExpression\" &&\n soleStatement.expression.callee?.type === \"Identifier\" &&\n SETTER_PATTERN.test(soleStatement.expression.callee.name)\n ) {\n context.report({\n node,\n message:\n \"useEffect(setState, []) on mount causes a flash — consider useSyncExternalStore or suppressHydrationWarning\",\n });\n }\n },\n }),\n};\n","import {\n DEPRECATED_RN_MODULE_REPLACEMENTS,\n LEGACY_EXPO_PACKAGE_REPLACEMENTS,\n LEGACY_SHADOW_STYLE_PROPERTIES,\n RAW_TEXT_PREVIEW_MAX_CHARS,\n REACT_NATIVE_LIST_COMPONENTS,\n REACT_NATIVE_TEXT_COMPONENTS,\n REACT_NATIVE_TEXT_COMPONENT_SUFFIXES,\n} from \"../constants.js\";\nimport { hasDirective, isMemberProperty } from \"../helpers.js\";\nimport type { EsTreeNode, Rule, RuleContext } from \"../types.js\";\n\nconst resolveJsxElementName = (openingElement: EsTreeNode): string | null => {\n const elementName = openingElement?.name;\n if (!elementName) return null;\n if (elementName.type === \"JSXIdentifier\") return elementName.name;\n if (elementName.type === \"JSXMemberExpression\") return elementName.property?.name ?? null;\n return null;\n};\n\nconst truncateText = (text: string): string =>\n text.length > RAW_TEXT_PREVIEW_MAX_CHARS\n ? `${text.slice(0, RAW_TEXT_PREVIEW_MAX_CHARS)}...`\n : text;\n\nconst isRawTextContent = (child: EsTreeNode): boolean => {\n if (child.type === \"JSXText\") return Boolean(child.value?.trim());\n if (child.type !== \"JSXExpressionContainer\" || !child.expression) return false;\n\n const expression = child.expression;\n return (\n (expression.type === \"Literal\" &&\n (typeof expression.value === \"string\" || typeof expression.value === \"number\")) ||\n expression.type === \"TemplateLiteral\"\n );\n};\n\nconst getRawTextDescription = (child: EsTreeNode): string => {\n if (child.type === \"JSXText\") {\n return `\"${truncateText(child.value.trim())}\"`;\n }\n\n if (child.type === \"JSXExpressionContainer\" && child.expression) {\n const expression = child.expression;\n if (expression.type === \"Literal\" && typeof expression.value === \"string\") {\n return `\"${truncateText(expression.value)}\"`;\n }\n if (expression.type === \"Literal\" && typeof expression.value === \"number\") {\n return `{${expression.value}}`;\n }\n if (expression.type === \"TemplateLiteral\") return \"template literal\";\n }\n\n return \"text content\";\n};\n\nconst isTextHandlingComponent = (elementName: string): boolean => {\n if (REACT_NATIVE_TEXT_COMPONENTS.has(elementName)) return true;\n return [...REACT_NATIVE_TEXT_COMPONENT_SUFFIXES].some((suffix) => elementName.endsWith(suffix));\n};\n\nexport const rnNoRawText: Rule = {\n create: (context: RuleContext) => {\n let isDomComponentFile = false;\n\n return {\n Program(programNode: EsTreeNode) {\n isDomComponentFile = hasDirective(programNode, \"use dom\");\n },\n JSXElement(node: EsTreeNode) {\n if (isDomComponentFile) return;\n\n const elementName = resolveJsxElementName(node.openingElement);\n if (elementName && isTextHandlingComponent(elementName)) return;\n\n for (const child of node.children ?? []) {\n if (!isRawTextContent(child)) continue;\n\n context.report({\n node: child,\n message: `Raw ${getRawTextDescription(child)} outside a <Text> component — this will crash on React Native`,\n });\n }\n },\n };\n },\n};\n\nexport const rnNoDeprecatedModules: Rule = {\n create: (context: RuleContext) => ({\n ImportDeclaration(node: EsTreeNode) {\n if (node.source?.value !== \"react-native\") return;\n\n for (const specifier of node.specifiers ?? []) {\n if (specifier.type !== \"ImportSpecifier\") continue;\n const importedName = specifier.imported?.name;\n if (!importedName) continue;\n\n const replacement = DEPRECATED_RN_MODULE_REPLACEMENTS[importedName];\n if (!replacement) continue;\n\n context.report({\n node: specifier,\n message: `\"${importedName}\" was removed from react-native — use ${replacement} instead`,\n });\n }\n },\n }),\n};\n\nexport const rnNoLegacyExpoPackages: Rule = {\n create: (context: RuleContext) => ({\n ImportDeclaration(node: EsTreeNode) {\n const source = node.source?.value;\n if (typeof source !== \"string\") return;\n\n for (const [packageName, replacement] of Object.entries(LEGACY_EXPO_PACKAGE_REPLACEMENTS)) {\n if (source === packageName || source.startsWith(`${packageName}/`)) {\n context.report({\n node,\n message: `\"${packageName}\" is deprecated — use ${replacement}`,\n });\n return;\n }\n }\n },\n }),\n};\n\nexport const rnNoDimensionsGet: Rule = {\n create: (context: RuleContext) => ({\n CallExpression(node: EsTreeNode) {\n if (node.callee?.type !== \"MemberExpression\") return;\n if (node.callee.object?.type !== \"Identifier\" || node.callee.object.name !== \"Dimensions\")\n return;\n\n if (isMemberProperty(node.callee, \"get\")) {\n context.report({\n node,\n message:\n \"Dimensions.get() does not update on screen rotation or resize — use useWindowDimensions() for reactive layout\",\n });\n }\n\n if (isMemberProperty(node.callee, \"addEventListener\")) {\n context.report({\n node,\n message:\n \"Dimensions.addEventListener() was removed in React Native 0.72 — use useWindowDimensions() instead\",\n });\n }\n },\n }),\n};\n\nexport const rnNoInlineFlatlistRenderitem: Rule = {\n create: (context: RuleContext) => ({\n JSXAttribute(node: EsTreeNode) {\n if (node.name?.type !== \"JSXIdentifier\" || node.name.name !== \"renderItem\") return;\n if (!node.value || node.value.type !== \"JSXExpressionContainer\") return;\n\n const openingElement = node.parent;\n if (!openingElement || openingElement.type !== \"JSXOpeningElement\") return;\n\n const listComponentName = resolveJsxElementName(openingElement);\n if (!listComponentName || !REACT_NATIVE_LIST_COMPONENTS.has(listComponentName)) return;\n\n const expression = node.value.expression;\n if (\n expression?.type !== \"ArrowFunctionExpression\" &&\n expression?.type !== \"FunctionExpression\"\n )\n return;\n\n context.report({\n node: expression,\n message: `Inline renderItem on <${listComponentName}> creates a new function reference every render — extract to a named function or wrap in useCallback`,\n });\n },\n }),\n};\n\nconst reportLegacyShadowProperties = (objectExpression: EsTreeNode, context: RuleContext): void => {\n const legacyShadowPropertyNames: string[] = [];\n\n for (const property of objectExpression.properties ?? []) {\n if (property.type !== \"Property\") continue;\n const propertyName = property.key?.type === \"Identifier\" ? property.key.name : null;\n if (propertyName && LEGACY_SHADOW_STYLE_PROPERTIES.has(propertyName)) {\n legacyShadowPropertyNames.push(propertyName);\n }\n }\n\n if (legacyShadowPropertyNames.length === 0) return;\n\n const quotedPropertyNames = legacyShadowPropertyNames.map((name) => `\"${name}\"`).join(\", \");\n context.report({\n node: objectExpression,\n message: `Legacy shadow style${legacyShadowPropertyNames.length > 1 ? \"s\" : \"\"} ${quotedPropertyNames} — use boxShadow for cross-platform shadows on the new architecture`,\n });\n};\n\nexport const rnNoLegacyShadowStyles: Rule = {\n create: (context: RuleContext) => ({\n JSXAttribute(node: EsTreeNode) {\n if (node.name?.type !== \"JSXIdentifier\" || node.name.name !== \"style\") return;\n if (node.value?.type !== \"JSXExpressionContainer\") return;\n\n const expression = node.value.expression;\n\n if (expression?.type === \"ObjectExpression\") {\n reportLegacyShadowProperties(expression, context);\n } else if (expression?.type === \"ArrayExpression\") {\n for (const element of expression.elements ?? []) {\n if (element?.type === \"ObjectExpression\") {\n reportLegacyShadowProperties(element, context);\n }\n }\n }\n },\n CallExpression(node: EsTreeNode) {\n if (node.callee?.type !== \"MemberExpression\") return;\n if (node.callee.object?.type !== \"Identifier\" || node.callee.object.name !== \"StyleSheet\")\n return;\n if (!isMemberProperty(node.callee, \"create\")) return;\n\n const stylesArgument = node.arguments?.[0];\n if (stylesArgument?.type !== \"ObjectExpression\") return;\n\n for (const styleDefinition of stylesArgument.properties ?? []) {\n if (styleDefinition.type !== \"Property\") continue;\n if (styleDefinition.value?.type !== \"ObjectExpression\") continue;\n reportLegacyShadowProperties(styleDefinition.value, context);\n }\n },\n }),\n};\n\nexport const rnPreferReanimated: Rule = {\n create: (context: RuleContext) => ({\n ImportDeclaration(node: EsTreeNode) {\n if (node.source?.value !== \"react-native\") return;\n\n for (const specifier of node.specifiers ?? []) {\n if (specifier.type !== \"ImportSpecifier\") continue;\n if (specifier.imported?.name !== \"Animated\") continue;\n\n context.report({\n node: specifier,\n message:\n \"Animated from react-native runs animations on the JS thread — use react-native-reanimated for performant UI-thread animations\",\n });\n }\n },\n }),\n};\n\nexport const rnNoSingleElementStyleArray: Rule = {\n create: (context: RuleContext) => ({\n JSXAttribute(node: EsTreeNode) {\n const propName = node.name?.type === \"JSXIdentifier\" ? node.name.name : null;\n if (!propName) return;\n if (propName !== \"style\" && !propName.endsWith(\"Style\")) return;\n if (node.value?.type !== \"JSXExpressionContainer\") return;\n\n const expression = node.value.expression;\n if (expression?.type !== \"ArrayExpression\") return;\n if (expression.elements?.length !== 1) return;\n\n context.report({\n node: expression,\n message: `Single-element style array on \"${propName}\" — use ${propName}={value} instead of ${propName}={[value]} to avoid unnecessary array allocation`,\n });\n },\n }),\n};\n","import {\n SECRET_FALSE_POSITIVE_SUFFIXES,\n SECRET_MIN_LENGTH_CHARS,\n SECRET_PATTERNS,\n SECRET_VARIABLE_PATTERN,\n} from \"../constants.js\";\nimport type { EsTreeNode, Rule, RuleContext } from \"../types.js\";\n\nexport const noEval: Rule = {\n create: (context: RuleContext) => ({\n CallExpression(node: EsTreeNode) {\n if (node.callee?.type === \"Identifier\" && node.callee.name === \"eval\") {\n context.report({\n node,\n message: \"eval() is a code injection risk — avoid dynamic code execution\",\n });\n return;\n }\n\n if (\n node.callee?.type === \"Identifier\" &&\n (node.callee.name === \"setTimeout\" || node.callee.name === \"setInterval\") &&\n node.arguments?.[0]?.type === \"Literal\" &&\n typeof node.arguments[0].value === \"string\"\n ) {\n context.report({\n node,\n message: `${node.callee.name}() with string argument executes code dynamically — use a function instead`,\n });\n }\n },\n NewExpression(node: EsTreeNode) {\n if (node.callee?.type === \"Identifier\" && node.callee.name === \"Function\") {\n context.report({\n node,\n message: \"new Function() is a code injection risk — avoid dynamic code execution\",\n });\n }\n },\n }),\n};\n\nexport const noSecretsInClientCode: Rule = {\n create: (context: RuleContext) => ({\n VariableDeclarator(node: EsTreeNode) {\n if (node.id?.type !== \"Identifier\") return;\n if (node.init?.type !== \"Literal\" || typeof node.init.value !== \"string\") return;\n\n const variableName = node.id.name;\n const literalValue = node.init.value;\n\n const trailingSuffix = variableName.split(\"_\").pop()?.toLowerCase() ?? \"\";\n const isUiConstant = SECRET_FALSE_POSITIVE_SUFFIXES.has(trailingSuffix);\n\n if (\n SECRET_VARIABLE_PATTERN.test(variableName) &&\n !isUiConstant &&\n literalValue.length > SECRET_MIN_LENGTH_CHARS\n ) {\n context.report({\n node,\n message: `Possible hardcoded secret in \"${variableName}\" — use environment variables instead`,\n });\n return;\n }\n\n if (SECRET_PATTERNS.some((pattern) => pattern.test(literalValue))) {\n context.report({\n node,\n message: \"Hardcoded secret detected — use environment variables instead\",\n });\n }\n },\n }),\n};\n","import {\n AUTH_CHECK_LOOKAHEAD_STATEMENTS,\n AUTH_FUNCTION_NAMES,\n SERVER_ACTION_DIRECTORY_PATTERN,\n SERVER_ACTION_FILE_PATTERN,\n} from \"../constants.js\";\nimport { hasDirective, hasUseServerDirective, walkAst } from \"../helpers.js\";\nimport type { EsTreeNode, Rule, RuleContext } from \"../types.js\";\n\nconst containsAuthCheck = (statements: EsTreeNode[]): boolean => {\n let foundAuthCall = false;\n for (const statement of statements) {\n walkAst(statement, (child: EsTreeNode) => {\n if (foundAuthCall) return;\n let callNode: EsTreeNode | null = null;\n if (child.type === \"CallExpression\") {\n callNode = child;\n } else if (child.type === \"AwaitExpression\" && child.argument?.type === \"CallExpression\") {\n callNode = child.argument;\n }\n\n if (\n callNode?.callee?.type === \"Identifier\" &&\n AUTH_FUNCTION_NAMES.has(callNode.callee.name)\n ) {\n foundAuthCall = true;\n }\n });\n }\n return foundAuthCall;\n};\n\nexport const serverAuthActions: Rule = {\n create: (context: RuleContext) => {\n let fileHasUseServerDirective = false;\n\n return {\n Program(programNode: EsTreeNode) {\n fileHasUseServerDirective = hasDirective(programNode, \"use server\");\n },\n ExportNamedDeclaration(node: EsTreeNode) {\n const declaration = node.declaration;\n if (declaration?.type !== \"FunctionDeclaration\" || !declaration?.async) return;\n\n const isServerAction = fileHasUseServerDirective || hasUseServerDirective(declaration);\n if (!isServerAction) return;\n\n const firstStatements = (declaration.body?.body ?? []).slice(\n 0,\n AUTH_CHECK_LOOKAHEAD_STATEMENTS,\n );\n if (!containsAuthCheck(firstStatements)) {\n const functionName = declaration.id?.name ?? \"anonymous\";\n context.report({\n node: declaration.id ?? node,\n message: `Server action \"${functionName}\" — add auth check (auth(), getSession(), etc.) at the top`,\n });\n }\n },\n };\n },\n};\n\nexport const serverAfterNonblocking: Rule = {\n create: (context: RuleContext) => {\n let fileHasUseServerDirective = false;\n\n return {\n Program(programNode: EsTreeNode) {\n fileHasUseServerDirective = hasDirective(programNode, \"use server\");\n },\n CallExpression(node: EsTreeNode) {\n if (!fileHasUseServerDirective) return;\n if (node.callee?.type !== \"MemberExpression\") return;\n if (node.callee.property?.type !== \"Identifier\") return;\n\n const objectName =\n node.callee.object?.type === \"Identifier\" ? node.callee.object.name : null;\n if (!objectName) return;\n\n const methodName = node.callee.property.name;\n const isLoggingCall =\n (objectName === \"console\" &&\n (methodName === \"log\" || methodName === \"info\" || methodName === \"warn\")) ||\n (objectName === \"analytics\" &&\n (methodName === \"track\" || methodName === \"identify\" || methodName === \"page\"));\n if (!isLoggingCall) return;\n\n context.report({\n node,\n message: `${objectName}.${methodName}() in server action — use after() for non-blocking logging/analytics`,\n });\n },\n };\n },\n};\n","import {\n CASCADING_SET_STATE_THRESHOLD,\n EFFECT_HOOK_NAMES,\n HOOKS_WITH_DEPS,\n RELATED_USE_STATE_THRESHOLD,\n TRIVIAL_INITIALIZER_NAMES,\n} from \"../constants.js\";\nimport {\n containsFetchCall,\n countSetStateCalls,\n extractDestructuredPropNames,\n getCallbackStatements,\n getEffectCallback,\n isComponentAssignment,\n isHookCall,\n isSetterIdentifier,\n isUppercaseName,\n walkAst,\n} from \"../helpers.js\";\nimport type { EsTreeNode, Rule, RuleContext } from \"../types.js\";\n\nexport const noDerivedStateEffect: Rule = {\n create: (context: RuleContext) => ({\n CallExpression(node: EsTreeNode) {\n if (!isHookCall(node, EFFECT_HOOK_NAMES) || node.arguments.length < 2) return;\n\n const callback = getEffectCallback(node);\n if (!callback) return;\n\n const depsNode = node.arguments[1];\n if (depsNode.type !== \"ArrayExpression\" || !depsNode.elements?.length) return;\n\n const dependencyNames = new Set(\n depsNode.elements\n .filter((element: EsTreeNode) => element?.type === \"Identifier\")\n .map((element: EsTreeNode) => element.name),\n );\n if (dependencyNames.size === 0) return;\n\n const statements = getCallbackStatements(callback);\n if (statements.length === 0) return;\n\n const containsOnlySetStateCalls = statements.every(\n (statement: EsTreeNode) =>\n statement.type === \"ExpressionStatement\" &&\n statement.expression?.type === \"CallExpression\" &&\n statement.expression.callee?.type === \"Identifier\" &&\n isSetterIdentifier(statement.expression.callee.name),\n );\n if (!containsOnlySetStateCalls) return;\n\n let allArgumentsDeriveFromDeps = true;\n let hasAnyDependencyReference = false;\n for (const statement of statements) {\n const setStateArguments = statement.expression.arguments;\n if (!setStateArguments?.length) continue;\n\n const referencedIdentifiers: string[] = [];\n walkAst(setStateArguments[0], (child: EsTreeNode) => {\n if (child.type === \"Identifier\") referencedIdentifiers.push(child.name);\n });\n\n const nonSetterIdentifiers = referencedIdentifiers.filter(\n (name) => !isSetterIdentifier(name),\n );\n\n if (nonSetterIdentifiers.some((name) => dependencyNames.has(name))) {\n hasAnyDependencyReference = true;\n }\n\n if (nonSetterIdentifiers.some((name) => !dependencyNames.has(name))) {\n allArgumentsDeriveFromDeps = false;\n break;\n }\n }\n\n if (allArgumentsDeriveFromDeps) {\n context.report({\n node,\n message: hasAnyDependencyReference\n ? \"Derived state in useEffect — compute during render instead\"\n : \"State reset in useEffect — use a key prop to reset component state when props change\",\n });\n }\n },\n }),\n};\n\nexport const noFetchInEffect: Rule = {\n create: (context: RuleContext) => ({\n CallExpression(node: EsTreeNode) {\n if (!isHookCall(node, EFFECT_HOOK_NAMES)) return;\n const callback = getEffectCallback(node);\n if (!callback) return;\n\n if (containsFetchCall(callback)) {\n context.report({\n node,\n message:\n \"fetch() inside useEffect — use a data fetching library (react-query, SWR) or server component\",\n });\n }\n },\n }),\n};\n\nexport const noCascadingSetState: Rule = {\n create: (context: RuleContext) => ({\n CallExpression(node: EsTreeNode) {\n if (!isHookCall(node, EFFECT_HOOK_NAMES)) return;\n const callback = getEffectCallback(node);\n if (!callback) return;\n\n const setStateCallCount = countSetStateCalls(callback);\n if (setStateCallCount >= CASCADING_SET_STATE_THRESHOLD) {\n context.report({\n node,\n message: `${setStateCallCount} setState calls in a single useEffect — consider using useReducer or deriving state`,\n });\n }\n },\n }),\n};\n\nexport const noEffectEventHandler: Rule = {\n create: (context: RuleContext) => ({\n CallExpression(node: EsTreeNode) {\n if (!isHookCall(node, EFFECT_HOOK_NAMES) || node.arguments.length < 2) return;\n\n const callback = getEffectCallback(node);\n if (!callback) return;\n\n const depsNode = node.arguments[1];\n if (depsNode.type !== \"ArrayExpression\" || !depsNode.elements?.length) return;\n\n const dependencyNames = new Set(\n depsNode.elements\n .filter((element: EsTreeNode) => element?.type === \"Identifier\")\n .map((element: EsTreeNode) => element.name),\n );\n\n const statements = getCallbackStatements(callback);\n if (statements.length !== 1) return;\n\n const soleStatement = statements[0];\n if (\n soleStatement.type === \"IfStatement\" &&\n soleStatement.test?.type === \"Identifier\" &&\n dependencyNames.has(soleStatement.test.name)\n ) {\n context.report({\n node,\n message:\n \"useEffect simulating an event handler — move logic to an actual event handler instead\",\n });\n }\n },\n }),\n};\n\nexport const noDerivedUseState: Rule = {\n create: (context: RuleContext) => {\n const componentPropNames = new Set<string>();\n\n return {\n FunctionDeclaration(node: EsTreeNode) {\n if (!node.id?.name || !isUppercaseName(node.id.name)) return;\n for (const name of extractDestructuredPropNames(node.params ?? [])) {\n componentPropNames.add(name);\n }\n },\n VariableDeclarator(node: EsTreeNode) {\n if (!isComponentAssignment(node)) return;\n for (const name of extractDestructuredPropNames(node.init?.params ?? [])) {\n componentPropNames.add(name);\n }\n },\n CallExpression(node: EsTreeNode) {\n if (!isHookCall(node, \"useState\") || !node.arguments?.length) return;\n const initializer = node.arguments[0];\n if (initializer.type !== \"Identifier\") return;\n\n if (componentPropNames.has(initializer.name)) {\n context.report({\n node,\n message: `useState initialized from prop \"${initializer.name}\" — if this value should stay in sync with the prop, derive it during render instead`,\n });\n }\n },\n };\n },\n};\n\nexport const preferUseReducer: Rule = {\n create: (context: RuleContext) => {\n const reportExcessiveUseState = (body: EsTreeNode, componentName: string): void => {\n if (body.type !== \"BlockStatement\") return;\n let useStateCount = 0;\n for (const statement of body.body ?? []) {\n if (statement.type !== \"VariableDeclaration\") continue;\n for (const declarator of statement.declarations ?? []) {\n if (isHookCall(declarator.init, \"useState\")) useStateCount++;\n }\n }\n if (useStateCount >= RELATED_USE_STATE_THRESHOLD) {\n context.report({\n node: body,\n message: `Component \"${componentName}\" has ${useStateCount} useState calls — consider useReducer for related state`,\n });\n }\n };\n\n return {\n FunctionDeclaration(node: EsTreeNode) {\n if (!node.id?.name || !isUppercaseName(node.id.name)) return;\n reportExcessiveUseState(node.body, node.id.name);\n },\n VariableDeclarator(node: EsTreeNode) {\n if (!isComponentAssignment(node)) return;\n reportExcessiveUseState(node.init.body, node.id.name);\n },\n };\n },\n};\n\nexport const rerenderLazyStateInit: Rule = {\n create: (context: RuleContext) => ({\n CallExpression(node: EsTreeNode) {\n if (!isHookCall(node, \"useState\") || !node.arguments?.length) return;\n const initializer = node.arguments[0];\n if (initializer.type !== \"CallExpression\") return;\n\n const calleeName =\n initializer.callee?.type === \"Identifier\"\n ? initializer.callee.name\n : (initializer.callee?.property?.name ?? \"fn\");\n\n if (TRIVIAL_INITIALIZER_NAMES.has(calleeName)) return;\n\n context.report({\n node: initializer,\n message: `useState(${calleeName}()) calls initializer on every render — use useState(() => ${calleeName}()) for lazy initialization`,\n });\n },\n }),\n};\n\nexport const rerenderFunctionalSetstate: Rule = {\n create: (context: RuleContext) => ({\n CallExpression(node: EsTreeNode) {\n if (node.callee?.type !== \"Identifier\" || !isSetterIdentifier(node.callee.name)) return;\n if (!node.arguments?.length) return;\n\n const argument = node.arguments[0];\n if (\n argument.type === \"BinaryExpression\" &&\n (argument.operator === \"+\" || argument.operator === \"-\") &&\n argument.left?.type === \"Identifier\"\n ) {\n context.report({\n node,\n message: `${node.callee.name}(${argument.left.name} ${argument.operator} ...) — use functional update to avoid stale closures`,\n });\n }\n },\n }),\n};\n\nexport const rerenderDependencies: Rule = {\n create: (context: RuleContext) => ({\n CallExpression(node: EsTreeNode) {\n if (!isHookCall(node, HOOKS_WITH_DEPS) || node.arguments.length < 2) return;\n const depsNode = node.arguments[1];\n if (depsNode.type !== \"ArrayExpression\") return;\n\n for (const element of depsNode.elements ?? []) {\n if (!element) continue;\n if (element.type === \"ObjectExpression\") {\n context.report({\n node: element,\n message:\n \"Object literal in useEffect deps — creates new reference every render, causing infinite re-runs\",\n });\n }\n if (element.type === \"ArrayExpression\") {\n context.report({\n node: element,\n message:\n \"Array literal in useEffect deps — creates new reference every render, causing infinite re-runs\",\n });\n }\n }\n },\n }),\n};\n","import {\n noGiantComponent,\n noNestedComponentDefinition,\n noRenderInRender,\n} from \"./rules/architecture.js\";\nimport {\n noBarrelImport,\n noFullLodashImport,\n noMoment,\n noUndeferredThirdParty,\n preferDynamicImport,\n useLazyMotion,\n} from \"./rules/bundle-size.js\";\nimport { clientPassiveEventListeners } from \"./rules/client.js\";\nimport {\n noArrayIndexAsKey,\n noPreventDefault,\n renderingConditionalRender,\n} from \"./rules/correctness.js\";\nimport {\n asyncParallel,\n jsBatchDomCss,\n jsCacheStorage,\n jsCombineIterations,\n jsEarlyExit,\n jsHoistRegexp,\n jsIndexMaps,\n jsMinMaxLoop,\n jsSetMapLookups,\n jsTosortedImmutable,\n} from \"./rules/js-performance.js\";\nimport {\n nextjsAsyncClientComponent,\n nextjsImageMissingSizes,\n nextjsInlineScriptMissingId,\n nextjsMissingMetadata,\n nextjsNoAElement,\n nextjsNoClientFetchForServerData,\n nextjsNoClientSideRedirect,\n nextjsNoCssLink,\n nextjsNoFontLink,\n nextjsNoHeadImport,\n nextjsNoImgElement,\n nextjsNoNativeScript,\n nextjsNoPolyfillScript,\n nextjsNoRedirectInTryCatch,\n nextjsNoSideEffectInGetHandler,\n nextjsNoUseSearchParamsWithoutSuspense,\n} from \"./rules/nextjs.js\";\nimport {\n noGlobalCssVariableAnimation,\n noLargeAnimatedBlur,\n noLayoutPropertyAnimation,\n noPermanentWillChange,\n noScaleFromZero,\n noTransitionAll,\n noUsememoSimpleExpression,\n renderingAnimateSvgWrapper,\n noInlinePropOnMemoComponent,\n renderingHydrationNoFlicker,\n rerenderMemoWithDefaultValue,\n} from \"./rules/performance.js\";\nimport {\n rnNoRawText,\n rnNoDeprecatedModules,\n rnNoLegacyExpoPackages,\n rnNoDimensionsGet,\n rnNoInlineFlatlistRenderitem,\n rnNoLegacyShadowStyles,\n rnPreferReanimated,\n rnNoSingleElementStyleArray,\n} from \"./rules/react-native.js\";\nimport { noEval, noSecretsInClientCode } from \"./rules/security.js\";\nimport { serverAfterNonblocking, serverAuthActions } from \"./rules/server.js\";\nimport {\n noCascadingSetState,\n noDerivedStateEffect,\n noDerivedUseState,\n noEffectEventHandler,\n noFetchInEffect,\n preferUseReducer,\n rerenderDependencies,\n rerenderFunctionalSetstate,\n rerenderLazyStateInit,\n} from \"./rules/state-and-effects.js\";\nimport type { RulePlugin } from \"./types.js\";\n\nconst plugin: RulePlugin = {\n meta: { name: \"react-doctor\" },\n rules: {\n \"no-derived-state-effect\": noDerivedStateEffect,\n \"no-fetch-in-effect\": noFetchInEffect,\n \"no-cascading-set-state\": noCascadingSetState,\n \"no-effect-event-handler\": noEffectEventHandler,\n \"no-derived-useState\": noDerivedUseState,\n \"prefer-useReducer\": preferUseReducer,\n \"rerender-lazy-state-init\": rerenderLazyStateInit,\n \"rerender-functional-setstate\": rerenderFunctionalSetstate,\n \"rerender-dependencies\": rerenderDependencies,\n\n \"no-giant-component\": noGiantComponent,\n \"no-render-in-render\": noRenderInRender,\n \"no-nested-component-definition\": noNestedComponentDefinition,\n\n \"no-usememo-simple-expression\": noUsememoSimpleExpression,\n \"no-layout-property-animation\": noLayoutPropertyAnimation,\n \"rerender-memo-with-default-value\": rerenderMemoWithDefaultValue,\n \"rendering-animate-svg-wrapper\": renderingAnimateSvgWrapper,\n \"no-inline-prop-on-memo-component\": noInlinePropOnMemoComponent,\n \"rendering-hydration-no-flicker\": renderingHydrationNoFlicker,\n\n \"no-transition-all\": noTransitionAll,\n \"no-global-css-variable-animation\": noGlobalCssVariableAnimation,\n \"no-large-animated-blur\": noLargeAnimatedBlur,\n \"no-scale-from-zero\": noScaleFromZero,\n \"no-permanent-will-change\": noPermanentWillChange,\n\n \"no-eval\": noEval,\n \"no-secrets-in-client-code\": noSecretsInClientCode,\n\n \"no-barrel-import\": noBarrelImport,\n \"no-full-lodash-import\": noFullLodashImport,\n \"no-moment\": noMoment,\n \"prefer-dynamic-import\": preferDynamicImport,\n \"use-lazy-motion\": useLazyMotion,\n \"no-undeferred-third-party\": noUndeferredThirdParty,\n\n \"no-array-index-as-key\": noArrayIndexAsKey,\n \"rendering-conditional-render\": renderingConditionalRender,\n \"no-prevent-default\": noPreventDefault,\n\n \"nextjs-no-img-element\": nextjsNoImgElement,\n \"nextjs-async-client-component\": nextjsAsyncClientComponent,\n \"nextjs-no-a-element\": nextjsNoAElement,\n \"nextjs-no-use-search-params-without-suspense\": nextjsNoUseSearchParamsWithoutSuspense,\n \"nextjs-no-client-fetch-for-server-data\": nextjsNoClientFetchForServerData,\n \"nextjs-missing-metadata\": nextjsMissingMetadata,\n \"nextjs-no-client-side-redirect\": nextjsNoClientSideRedirect,\n \"nextjs-no-redirect-in-try-catch\": nextjsNoRedirectInTryCatch,\n \"nextjs-image-missing-sizes\": nextjsImageMissingSizes,\n \"nextjs-no-native-script\": nextjsNoNativeScript,\n \"nextjs-inline-script-missing-id\": nextjsInlineScriptMissingId,\n \"nextjs-no-font-link\": nextjsNoFontLink,\n \"nextjs-no-css-link\": nextjsNoCssLink,\n \"nextjs-no-polyfill-script\": nextjsNoPolyfillScript,\n \"nextjs-no-head-import\": nextjsNoHeadImport,\n \"nextjs-no-side-effect-in-get-handler\": nextjsNoSideEffectInGetHandler,\n\n \"server-auth-actions\": serverAuthActions,\n \"server-after-nonblocking\": serverAfterNonblocking,\n\n \"client-passive-event-listeners\": clientPassiveEventListeners,\n\n \"js-combine-iterations\": jsCombineIterations,\n \"js-tosorted-immutable\": jsTosortedImmutable,\n \"js-hoist-regexp\": jsHoistRegexp,\n \"js-min-max-loop\": jsMinMaxLoop,\n \"js-set-map-lookups\": jsSetMapLookups,\n \"js-batch-dom-css\": jsBatchDomCss,\n \"js-index-maps\": jsIndexMaps,\n \"js-cache-storage\": jsCacheStorage,\n \"js-early-exit\": jsEarlyExit,\n \"async-parallel\": asyncParallel,\n\n \"rn-no-raw-text\": rnNoRawText,\n \"rn-no-deprecated-modules\": rnNoDeprecatedModules,\n \"rn-no-legacy-expo-packages\": rnNoLegacyExpoPackages,\n \"rn-no-dimensions-get\": rnNoDimensionsGet,\n \"rn-no-inline-flatlist-renderitem\": rnNoInlineFlatlistRenderitem,\n \"rn-no-legacy-shadow-styles\": rnNoLegacyShadowStyles,\n \"rn-prefer-reanimated\": rnPreferReanimated,\n \"rn-no-single-element-style-array\": rnNoSingleElementStyleArray,\n },\n};\n\nexport default plugin;\n"],"mappings":";AAAA,MAAa,iCAAiC;AAC9C,MAAa,gCAAgC;AAC7C,MAAa,8BAA8B;AAC3C,MAAa,yBAAyB;AACtC,MAAa,mCAAmC;AAChD,MAAa,6BAA6B;AAC1C,MAAa,0BAA0B;AACvC,MAAa,kCAAkC;AAE/C,MAAa,oBAAoB,IAAI,IAAI;CACvC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;AAEF,MAAa,uBAAuB,IAAI,IAAI;CAC1C;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;AAEF,MAAa,kBAAkB,IAAI,IAAI;CACrC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;AAEF,MAAa,qBAAqB,IAAI,IAAI,CAAC,QAAQ,CAAC;AACpD,MAAa,uBAAuB,IAAI,IAAI;CAAC;CAAS;CAAM;CAAM,CAAC;AACnE,MAAa,wBAAwB,IAAI,IAAI;CAAC;CAAS;CAAO;CAAI,CAAC;AACnE,MAAa,wBAAwB;CACnC;CACA;CACA;CACA;CACA;CACD;AACD,MAAa,sBAAsB,IAAI,IAAI;CACzC;CACA;CACA;CACA;CACA;CACD,CAAC;AAEF,MAAa,aAAa;CACxB;CACA;CACA;CACA;CACA;CACD;AAED,MAAa,sBAAsB,IAAI,IAAI;CACzC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;AAEF,MAAa,kBAAkB;CAC7B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD;AAED,MAAa,0BAA0B;AAEvC,MAAa,iCAAiC,IAAI,IAAI;CACpD;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CAC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"}
|
|
1
|
+
{"version":3,"file":"react-doctor-plugin.js","names":[],"sources":["../src/plugin/constants.ts","../src/plugin/helpers.ts","../src/plugin/rules/architecture.ts","../src/plugin/rules/bundle-size.ts","../src/plugin/rules/client.ts","../src/plugin/rules/correctness.ts","../src/plugin/rules/js-performance.ts","../src/plugin/rules/nextjs.ts","../src/plugin/rules/performance.ts","../src/plugin/rules/react-native.ts","../src/plugin/rules/security.ts","../src/plugin/rules/server.ts","../src/plugin/rules/state-and-effects.ts","../src/plugin/index.ts"],"sourcesContent":["export const GIANT_COMPONENT_LINE_THRESHOLD = 300;\nexport const CASCADING_SET_STATE_THRESHOLD = 3;\nexport const RELATED_USE_STATE_THRESHOLD = 5;\nexport const DEEP_NESTING_THRESHOLD = 3;\nexport const DUPLICATE_STORAGE_READ_THRESHOLD = 2;\nexport const SEQUENTIAL_AWAIT_THRESHOLD = 3;\nexport const SECRET_MIN_LENGTH_CHARS = 8;\nexport const AUTH_CHECK_LOOKAHEAD_STATEMENTS = 3;\n\nexport const LAYOUT_PROPERTIES = new Set([\n \"width\",\n \"height\",\n \"top\",\n \"left\",\n \"right\",\n \"bottom\",\n \"padding\",\n \"paddingTop\",\n \"paddingRight\",\n \"paddingBottom\",\n \"paddingLeft\",\n \"margin\",\n \"marginTop\",\n \"marginRight\",\n \"marginBottom\",\n \"marginLeft\",\n \"borderWidth\",\n \"fontSize\",\n \"lineHeight\",\n \"gap\",\n]);\n\nexport const MOTION_ANIMATE_PROPS = new Set([\n \"animate\",\n \"initial\",\n \"exit\",\n \"whileHover\",\n \"whileTap\",\n \"whileFocus\",\n \"whileDrag\",\n \"whileInView\",\n]);\n\nexport const HEAVY_LIBRARIES = new Set([\n \"@monaco-editor/react\",\n \"monaco-editor\",\n \"recharts\",\n \"@react-pdf/renderer\",\n \"react-quill\",\n \"@codemirror/view\",\n \"@codemirror/state\",\n \"chart.js\",\n \"react-chartjs-2\",\n \"@toast-ui/editor\",\n \"draft-js\",\n]);\n\nexport const FETCH_CALLEE_NAMES = new Set([\"fetch\"]);\nexport const FETCH_MEMBER_OBJECTS = new Set([\"axios\", \"ky\", \"got\"]);\nexport const INDEX_PARAMETER_NAMES = new Set([\"index\", \"idx\", \"i\"]);\nexport const BARREL_INDEX_SUFFIXES = [\n \"/index\",\n \"/index.js\",\n \"/index.ts\",\n \"/index.tsx\",\n \"/index.mjs\",\n];\nexport const PASSIVE_EVENT_NAMES = new Set([\n \"scroll\",\n \"wheel\",\n \"touchstart\",\n \"touchmove\",\n \"touchend\",\n]);\n\nexport const LOOP_TYPES = [\n \"ForStatement\",\n \"ForInStatement\",\n \"ForOfStatement\",\n \"WhileStatement\",\n \"DoWhileStatement\",\n];\n\nexport const AUTH_FUNCTION_NAMES = new Set([\n \"auth\",\n \"getSession\",\n \"getServerSession\",\n \"getUser\",\n \"requireAuth\",\n \"checkAuth\",\n \"verifyAuth\",\n \"authenticate\",\n \"currentUser\",\n \"getAuth\",\n \"validateSession\",\n]);\n\nexport const SECRET_PATTERNS = [\n /^sk_live_/,\n /^sk_test_/,\n /^AKIA[0-9A-Z]{16}$/,\n /^ghp_[a-zA-Z0-9]{36}$/,\n /^gho_[a-zA-Z0-9]{36}$/,\n /^github_pat_/,\n /^glpat-/,\n /^xox[bporas]-/,\n /^sk-[a-zA-Z0-9]{32,}$/,\n];\n\nexport const SECRET_VARIABLE_PATTERN = /(?:api_?key|secret|token|password|credential|auth)/i;\n\nexport const SECRET_FALSE_POSITIVE_SUFFIXES = new Set([\n \"modal\",\n \"label\",\n \"text\",\n \"title\",\n \"name\",\n \"id\",\n \"key\",\n \"url\",\n \"path\",\n \"route\",\n \"page\",\n \"param\",\n \"field\",\n \"column\",\n \"header\",\n \"placeholder\",\n \"description\",\n \"type\",\n \"icon\",\n \"class\",\n \"style\",\n \"variant\",\n \"event\",\n \"action\",\n \"status\",\n \"state\",\n \"mode\",\n \"flag\",\n \"option\",\n \"config\",\n \"message\",\n \"error\",\n \"display\",\n \"view\",\n \"component\",\n \"element\",\n \"container\",\n \"wrapper\",\n \"button\",\n \"link\",\n \"input\",\n \"select\",\n \"dialog\",\n \"menu\",\n \"form\",\n \"step\",\n \"index\",\n \"count\",\n \"length\",\n \"role\",\n \"scope\",\n \"context\",\n \"provider\",\n \"ref\",\n \"handler\",\n \"query\",\n \"schema\",\n \"constant\",\n]);\n\nexport const LOADING_STATE_PATTERN = /^(?:isLoading|isPending)$/;\n\nexport const GENERIC_EVENT_SUFFIXES = new Set([\"Click\", \"Change\", \"Input\", \"Blur\", \"Focus\"]);\n\nexport const TRIVIAL_INITIALIZER_NAMES = new Set([\n \"Boolean\",\n \"String\",\n \"Number\",\n \"Array\",\n \"Object\",\n \"parseInt\",\n \"parseFloat\",\n]);\n\nexport const SETTER_PATTERN = /^set[A-Z]/;\nexport const RENDER_FUNCTION_PATTERN = /^render[A-Z]/;\nexport const UPPERCASE_PATTERN = /^[A-Z]/;\nexport const PAGE_FILE_PATTERN = /\\/page\\.(tsx?|jsx?)$/;\nexport const PAGE_OR_LAYOUT_FILE_PATTERN = /\\/(page|layout)\\.(tsx?|jsx?)$/;\n\nexport const INTERNAL_PAGE_PATH_PATTERN =\n /\\/(?:(?:\\((?:dashboard|admin|settings|account|internal|manage|console|portal|auth|onboarding|app|ee|protected)\\))|(?:dashboard|admin|settings|account|internal|manage|console|portal))\\//i;\n\nexport const TEST_FILE_PATTERN = /\\.(?:test|spec|stories)\\.[tj]sx?$/;\nexport const OG_ROUTE_PATTERN = /\\/og\\b/i;\n\nexport const PAGES_DIRECTORY_PATTERN = /\\/pages\\//;\nexport const SERVER_ACTION_FILE_PATTERN = /actions?\\.(tsx?|jsx?)$/;\nexport const SERVER_ACTION_DIRECTORY_PATTERN = /\\/actions\\//;\n\nexport const NEXTJS_NAVIGATION_FUNCTIONS = new Set([\n \"redirect\",\n \"permanentRedirect\",\n \"notFound\",\n \"forbidden\",\n \"unauthorized\",\n]);\n\nexport const GOOGLE_FONTS_PATTERN = /fonts\\.googleapis\\.com/;\n\nexport const POLYFILL_SCRIPT_PATTERN = /polyfill\\.io|polyfill\\.min\\.js|cdn\\.polyfill/;\n\nexport const EXECUTABLE_SCRIPT_TYPES = new Set([\n \"text/javascript\",\n \"application/javascript\",\n \"module\",\n]);\n\nexport const APP_DIRECTORY_PATTERN = /\\/app\\//;\n\nexport const ROUTE_HANDLER_FILE_PATTERN = /\\/route\\.(tsx?|jsx?)$/;\n\nexport const MUTATION_METHOD_NAMES = new Set([\n \"create\",\n \"insert\",\n \"insertInto\",\n \"update\",\n \"upsert\",\n \"delete\",\n \"remove\",\n \"destroy\",\n \"set\",\n \"append\",\n]);\n\nexport const MUTATING_HTTP_METHODS = new Set([\"POST\", \"PUT\", \"DELETE\", \"PATCH\"]);\n\nexport const MUTATING_ROUTE_SEGMENTS = new Set([\n \"logout\",\n \"log-out\",\n \"signout\",\n \"sign-out\",\n \"unsubscribe\",\n \"delete\",\n \"remove\",\n \"revoke\",\n \"cancel\",\n \"deactivate\",\n]);\n\nexport const EFFECT_HOOK_NAMES = new Set([\"useEffect\", \"useLayoutEffect\"]);\nexport const HOOKS_WITH_DEPS = new Set([\"useEffect\", \"useLayoutEffect\", \"useMemo\", \"useCallback\"]);\nexport const CHAINABLE_ITERATION_METHODS = new Set([\"map\", \"filter\", \"forEach\", \"flatMap\"]);\nexport const STORAGE_OBJECTS = new Set([\"localStorage\", \"sessionStorage\"]);\n\nexport const LARGE_BLUR_THRESHOLD_PX = 10;\nexport const BLUR_VALUE_PATTERN = /blur\\((\\d+(?:\\.\\d+)?)px\\)/;\nexport const ANIMATION_CALLBACK_NAMES = new Set([\"requestAnimationFrame\", \"setInterval\"]);\nexport const MOTION_LIBRARY_PACKAGES = new Set([\"framer-motion\", \"motion\"]);\n\nexport const RAW_TEXT_PREVIEW_MAX_CHARS = 30;\n\nexport const REACT_NATIVE_TEXT_COMPONENTS = new Set([\n \"Text\",\n \"TextInput\",\n \"Typography\",\n \"Paragraph\",\n \"Span\",\n \"H1\",\n \"H2\",\n \"H3\",\n \"H4\",\n \"H5\",\n \"H6\",\n]);\n\nexport const REACT_NATIVE_TEXT_COMPONENT_KEYWORDS = new Set([\n \"Text\",\n \"Title\",\n \"Label\",\n \"Heading\",\n \"Caption\",\n \"Subtitle\",\n \"Typography\",\n \"Paragraph\",\n \"Description\",\n \"Body\",\n]);\n\nexport const DEPRECATED_RN_MODULE_REPLACEMENTS: Record<string, string> = {\n AsyncStorage: \"@react-native-async-storage/async-storage\",\n Picker: \"@react-native-picker/picker\",\n PickerIOS: \"@react-native-picker/picker\",\n DatePickerIOS: \"@react-native-community/datetimepicker\",\n DatePickerAndroid: \"@react-native-community/datetimepicker\",\n ProgressBarAndroid: \"a community alternative\",\n ProgressViewIOS: \"a community alternative\",\n SafeAreaView: \"react-native-safe-area-context\",\n Slider: \"@react-native-community/slider\",\n ViewPagerAndroid: \"react-native-pager-view\",\n WebView: \"react-native-webview\",\n NetInfo: \"@react-native-community/netinfo\",\n CameraRoll: \"@react-native-camera-roll/camera-roll\",\n Clipboard: \"@react-native-clipboard/clipboard\",\n ImageEditor: \"@react-native-community/image-editor\",\n MaskedViewIOS: \"@react-native-masked-view/masked-view\",\n};\n\nexport const LEGACY_EXPO_PACKAGE_REPLACEMENTS: Record<string, string> = {\n \"expo-av\": \"expo-audio for audio and expo-video for video\",\n \"expo-permissions\": \"the permissions API in each module (e.g. Camera.requestPermissionsAsync())\",\n \"@expo/vector-icons\":\n \"expo-symbols or expo-image (see https://docs.expo.dev/versions/latest/sdk/symbols/)\",\n};\n\nexport const REACT_NATIVE_LIST_COMPONENTS = new Set([\n \"FlatList\",\n \"SectionList\",\n \"VirtualizedList\",\n \"FlashList\",\n]);\n\nexport const LEGACY_SHADOW_STYLE_PROPERTIES = new Set([\n \"shadowColor\",\n \"shadowOffset\",\n \"shadowOpacity\",\n \"shadowRadius\",\n \"elevation\",\n]);\n","import {\n FETCH_CALLEE_NAMES,\n FETCH_MEMBER_OBJECTS,\n LOOP_TYPES,\n MUTATING_HTTP_METHODS,\n MUTATION_METHOD_NAMES,\n SETTER_PATTERN,\n UPPERCASE_PATTERN,\n} from \"./constants.js\";\nimport type { EsTreeNode, RuleVisitors } from \"./types.js\";\n\nexport const walkAst = (node: EsTreeNode, visitor: (child: EsTreeNode) => void): void => {\n if (!node || typeof node !== \"object\") return;\n visitor(node);\n for (const key of Object.keys(node)) {\n if (key === \"parent\") continue;\n const child = node[key];\n if (Array.isArray(child)) {\n for (const item of child) {\n if (item && typeof item === \"object\" && item.type) {\n walkAst(item, visitor);\n }\n }\n } else if (child && typeof child === \"object\" && child.type) {\n walkAst(child, visitor);\n }\n }\n};\n\nexport const isSetterIdentifier = (name: string): boolean => SETTER_PATTERN.test(name);\n\nexport const isSetterCall = (node: EsTreeNode): boolean =>\n node.type === \"CallExpression\" &&\n node.callee?.type === \"Identifier\" &&\n isSetterIdentifier(node.callee.name);\n\nexport const isUppercaseName = (name: string): boolean => UPPERCASE_PATTERN.test(name);\n\nexport const isMemberProperty = (node: EsTreeNode, propertyName: string): boolean =>\n node.type === \"MemberExpression\" &&\n node.property?.type === \"Identifier\" &&\n node.property.name === propertyName;\n\nexport const getEffectCallback = (node: EsTreeNode): EsTreeNode | null => {\n if (!node.arguments?.length) return null;\n const callback = node.arguments[0];\n if (callback.type === \"ArrowFunctionExpression\" || callback.type === \"FunctionExpression\") {\n return callback;\n }\n return null;\n};\n\nexport const getCallbackStatements = (callback: EsTreeNode): EsTreeNode[] => {\n if (callback.body?.type === \"BlockStatement\") {\n return callback.body.body ?? [];\n }\n return callback.body ? [callback.body] : [];\n};\n\nexport const countSetStateCalls = (node: EsTreeNode): number => {\n let setStateCallCount = 0;\n walkAst(node, (child) => {\n if (isSetterCall(child)) setStateCallCount++;\n });\n return setStateCallCount;\n};\n\nexport const isSimpleExpression = (node: EsTreeNode | null): boolean => {\n if (!node) return false;\n switch (node.type) {\n case \"Identifier\":\n case \"Literal\":\n case \"TemplateLiteral\":\n return true;\n case \"BinaryExpression\":\n return isSimpleExpression(node.left) && isSimpleExpression(node.right);\n case \"UnaryExpression\":\n return isSimpleExpression(node.argument);\n case \"MemberExpression\":\n return !node.computed;\n case \"ConditionalExpression\":\n return (\n isSimpleExpression(node.test) &&\n isSimpleExpression(node.consequent) &&\n isSimpleExpression(node.alternate)\n );\n default:\n return false;\n }\n};\n\nexport const isComponentDeclaration = (node: EsTreeNode): boolean =>\n node.type === \"FunctionDeclaration\" && Boolean(node.id?.name) && isUppercaseName(node.id.name);\n\nexport const isComponentAssignment = (node: EsTreeNode): boolean =>\n node.type === \"VariableDeclarator\" &&\n node.id?.type === \"Identifier\" &&\n isUppercaseName(node.id.name) &&\n Boolean(node.init) &&\n (node.init.type === \"ArrowFunctionExpression\" || node.init.type === \"FunctionExpression\");\n\nexport const getCalleeName = (node: EsTreeNode): string | null => {\n if (node.callee?.type === \"Identifier\") return node.callee.name;\n if (node.callee?.type === \"MemberExpression\" && node.callee.property?.type === \"Identifier\") {\n return node.callee.property.name;\n }\n return null;\n};\n\nexport const isHookCall = (node: EsTreeNode, hookName: string | Set<string>): boolean => {\n if (node.type !== \"CallExpression\") return false;\n const calleeName = getCalleeName(node);\n if (!calleeName) return false;\n return typeof hookName === \"string\" ? calleeName === hookName : hookName.has(calleeName);\n};\n\nexport const hasDirective = (programNode: EsTreeNode, directive: string): boolean =>\n Boolean(\n programNode.body?.some(\n (statement: EsTreeNode) =>\n statement.type === \"ExpressionStatement\" &&\n statement.expression?.type === \"Literal\" &&\n statement.expression.value === directive,\n ),\n );\n\nexport const hasUseServerDirective = (node: EsTreeNode): boolean => {\n if (node.body?.type !== \"BlockStatement\") return false;\n return Boolean(\n node.body.body?.some(\n (statement: EsTreeNode) =>\n statement.type === \"ExpressionStatement\" && statement.directive === \"use server\",\n ),\n );\n};\n\nexport const containsFetchCall = (node: EsTreeNode): boolean => {\n let didFindFetchCall = false;\n walkAst(node, (child) => {\n if (didFindFetchCall || child.type !== \"CallExpression\") return;\n if (child.callee?.type === \"Identifier\" && FETCH_CALLEE_NAMES.has(child.callee.name)) {\n didFindFetchCall = true;\n }\n if (\n child.callee?.type === \"MemberExpression\" &&\n child.callee.object?.type === \"Identifier\" &&\n FETCH_MEMBER_OBJECTS.has(child.callee.object.name)\n ) {\n didFindFetchCall = true;\n }\n });\n return didFindFetchCall;\n};\n\nexport const findJsxAttribute = (\n attributes: EsTreeNode[],\n attributeName: string,\n): EsTreeNode | undefined =>\n attributes?.find(\n (attr: EsTreeNode) =>\n attr.type === \"JSXAttribute\" &&\n attr.name?.type === \"JSXIdentifier\" &&\n attr.name.name === attributeName,\n );\n\nexport const hasJsxAttribute = (attributes: EsTreeNode[], attributeName: string): boolean =>\n Boolean(findJsxAttribute(attributes, attributeName));\n\nexport const createLoopAwareVisitors = (\n innerVisitors: Record<string, (node: EsTreeNode) => void>,\n): RuleVisitors => {\n let loopDepth = 0;\n const incrementLoopDepth = (): void => {\n loopDepth++;\n };\n const decrementLoopDepth = (): void => {\n loopDepth--;\n };\n\n const visitors: RuleVisitors = {};\n\n for (const loopType of LOOP_TYPES) {\n visitors[loopType] = incrementLoopDepth;\n visitors[`${loopType}:exit`] = decrementLoopDepth;\n }\n\n for (const [nodeType, handler] of Object.entries(innerVisitors)) {\n visitors[nodeType] = (node: EsTreeNode) => {\n if (loopDepth > 0) handler(node);\n };\n }\n\n return visitors;\n};\n\nconst isCookiesOrHeadersCall = (node: EsTreeNode, methodName: string): boolean => {\n if (node.type !== \"CallExpression\" || node.callee?.type !== \"MemberExpression\") return false;\n const { object, property } = node.callee;\n if (property?.type !== \"Identifier\" || !MUTATION_METHOD_NAMES.has(property.name)) return false;\n if (object?.type !== \"CallExpression\" || object.callee?.type !== \"Identifier\") return false;\n return object.callee.name === methodName;\n};\n\nconst isMutatingDbCall = (node: EsTreeNode): boolean => {\n if (node.type !== \"CallExpression\" || node.callee?.type !== \"MemberExpression\") return false;\n const { property } = node.callee;\n return property?.type === \"Identifier\" && MUTATION_METHOD_NAMES.has(property.name);\n};\n\nconst isMutatingFetchCall = (node: EsTreeNode): boolean => {\n if (node.type !== \"CallExpression\") return false;\n if (node.callee?.type !== \"Identifier\" || node.callee.name !== \"fetch\") return false;\n const optionsArgument = node.arguments?.[1];\n if (!optionsArgument || optionsArgument.type !== \"ObjectExpression\") return false;\n return optionsArgument.properties?.some(\n (property: EsTreeNode) =>\n property.type === \"Property\" &&\n property.key?.type === \"Identifier\" &&\n property.key.name === \"method\" &&\n property.value?.type === \"Literal\" &&\n typeof property.value.value === \"string\" &&\n MUTATING_HTTP_METHODS.has(property.value.value.toUpperCase()),\n );\n};\n\nexport const findSideEffect = (node: EsTreeNode): string | null => {\n let sideEffectDescription: string | null = null;\n walkAst(node, (child: EsTreeNode) => {\n if (sideEffectDescription) return;\n if (isCookiesOrHeadersCall(child, \"cookies\")) {\n const methodName = child.callee.property.name;\n sideEffectDescription = `cookies().${methodName}()`;\n } else if (isCookiesOrHeadersCall(child, \"headers\")) {\n const methodName = child.callee.property.name;\n sideEffectDescription = `headers().${methodName}()`;\n } else if (isMutatingFetchCall(child)) {\n const methodProperty = child.arguments[1].properties.find(\n (property: EsTreeNode) =>\n property.key?.type === \"Identifier\" && property.key.name === \"method\",\n );\n sideEffectDescription = `fetch() with method ${methodProperty.value.value}`;\n } else if (isMutatingDbCall(child)) {\n const methodName = child.callee.property.name;\n const objectName =\n child.callee.object?.type === \"Identifier\" ? child.callee.object.name : null;\n sideEffectDescription = objectName ? `${objectName}.${methodName}()` : `.${methodName}()`;\n }\n });\n return sideEffectDescription;\n};\n\nexport const extractDestructuredPropNames = (params: EsTreeNode[]): Set<string> => {\n const propNames = new Set<string>();\n for (const param of params) {\n if (param.type === \"ObjectPattern\") {\n for (const property of param.properties ?? []) {\n if (property.type === \"Property\" && property.key?.type === \"Identifier\") {\n propNames.add(property.key.name);\n }\n }\n } else if (param.type === \"Identifier\") {\n propNames.add(param.name);\n }\n }\n return propNames;\n};\n","import {\n GENERIC_EVENT_SUFFIXES,\n GIANT_COMPONENT_LINE_THRESHOLD,\n RENDER_FUNCTION_PATTERN,\n} from \"../constants.js\";\nimport { isComponentAssignment, isComponentDeclaration, isUppercaseName } from \"../helpers.js\";\nimport type { EsTreeNode, Rule, RuleContext } from \"../types.js\";\n\nexport const noGenericHandlerNames: Rule = {\n create: (context: RuleContext) => ({\n JSXAttribute(node: EsTreeNode) {\n if (node.name?.type !== \"JSXIdentifier\" || !node.name.name.startsWith(\"on\")) return;\n if (!node.value || node.value.type !== \"JSXExpressionContainer\") return;\n\n const eventSuffix = node.name.name.slice(2);\n if (!GENERIC_EVENT_SUFFIXES.has(eventSuffix)) return;\n\n const mirroredHandlerName = `handle${eventSuffix}`;\n const expression = node.value.expression;\n if (expression?.type === \"Identifier\" && expression.name === mirroredHandlerName) {\n context.report({\n node,\n message: `Non-descriptive handler name \"${expression.name}\" — name should describe what it does, not when it runs`,\n });\n }\n },\n }),\n};\n\nexport const noGiantComponent: Rule = {\n create: (context: RuleContext) => {\n const reportOversizedComponent = (\n nameNode: EsTreeNode,\n componentName: string,\n bodyNode: EsTreeNode,\n ): void => {\n if (!bodyNode.loc) return;\n const lineCount = bodyNode.loc.end.line - bodyNode.loc.start.line + 1;\n if (lineCount > GIANT_COMPONENT_LINE_THRESHOLD) {\n context.report({\n node: nameNode,\n message: `Component \"${componentName}\" is ${lineCount} lines — consider breaking it into smaller focused components`,\n });\n }\n };\n\n return {\n FunctionDeclaration(node: EsTreeNode) {\n if (!node.id?.name || !isUppercaseName(node.id.name)) return;\n reportOversizedComponent(node.id, node.id.name, node);\n },\n VariableDeclarator(node: EsTreeNode) {\n if (!isComponentAssignment(node)) return;\n reportOversizedComponent(node.id, node.id.name, node.init);\n },\n };\n },\n};\n\nexport const noRenderInRender: Rule = {\n create: (context: RuleContext) => ({\n JSXExpressionContainer(node: EsTreeNode) {\n const expression = node.expression;\n if (expression?.type !== \"CallExpression\") return;\n\n let calleeName: string | null = null;\n if (expression.callee?.type === \"Identifier\") {\n calleeName = expression.callee.name;\n } else if (\n expression.callee?.type === \"MemberExpression\" &&\n expression.callee.property?.type === \"Identifier\"\n ) {\n calleeName = expression.callee.property.name;\n }\n\n if (calleeName && RENDER_FUNCTION_PATTERN.test(calleeName)) {\n context.report({\n node: expression,\n message: `Inline render function \"${calleeName}()\" — extract to a separate component for proper reconciliation`,\n });\n }\n },\n }),\n};\n\nexport const noNestedComponentDefinition: Rule = {\n create: (context: RuleContext) => {\n const componentStack: string[] = [];\n\n return {\n FunctionDeclaration(node: EsTreeNode) {\n if (!isComponentDeclaration(node)) return;\n if (componentStack.length > 0) {\n context.report({\n node: node.id,\n message: `Component \"${node.id.name}\" defined inside \"${componentStack[componentStack.length - 1]}\" — creates new instance every render, destroying state`,\n });\n }\n componentStack.push(node.id.name);\n },\n \"FunctionDeclaration:exit\"(node: EsTreeNode) {\n if (isComponentDeclaration(node)) componentStack.pop();\n },\n VariableDeclarator(node: EsTreeNode) {\n if (!isComponentAssignment(node)) return;\n if (componentStack.length > 0) {\n context.report({\n node: node.id,\n message: `Component \"${node.id.name}\" defined inside \"${componentStack[componentStack.length - 1]}\" — creates new instance every render, destroying state`,\n });\n }\n componentStack.push(node.id.name);\n },\n \"VariableDeclarator:exit\"(node: EsTreeNode) {\n if (isComponentAssignment(node)) componentStack.pop();\n },\n };\n },\n};\n","import { BARREL_INDEX_SUFFIXES, HEAVY_LIBRARIES } from \"../constants.js\";\nimport { findJsxAttribute, hasJsxAttribute } from \"../helpers.js\";\nimport type { EsTreeNode, Rule, RuleContext } from \"../types.js\";\n\nexport const noBarrelImport: Rule = {\n create: (context: RuleContext) => {\n let didReportForFile = false;\n\n return {\n ImportDeclaration(node: EsTreeNode) {\n if (didReportForFile) return;\n\n const source = node.source?.value;\n if (typeof source !== \"string\" || !source.startsWith(\".\")) return;\n\n if (BARREL_INDEX_SUFFIXES.some((suffix) => source.endsWith(suffix))) {\n didReportForFile = true;\n context.report({\n node,\n message:\n \"Import from barrel/index file — import directly from the source module for better tree-shaking\",\n });\n }\n },\n };\n },\n};\n\nexport const noFullLodashImport: Rule = {\n create: (context: RuleContext) => ({\n ImportDeclaration(node: EsTreeNode) {\n const source = node.source?.value;\n if (source === \"lodash\" || source === \"lodash-es\") {\n context.report({\n node,\n message: \"Importing entire lodash library — import from 'lodash/functionName' instead\",\n });\n }\n },\n }),\n};\n\nexport const noMoment: Rule = {\n create: (context: RuleContext) => ({\n ImportDeclaration(node: EsTreeNode) {\n if (node.source?.value === \"moment\") {\n context.report({\n node,\n message: 'moment.js is 300kb+ — use \"date-fns\" or \"dayjs\" instead',\n });\n }\n },\n }),\n};\n\nexport const preferDynamicImport: Rule = {\n create: (context: RuleContext) => ({\n ImportDeclaration(node: EsTreeNode) {\n const source = node.source?.value;\n if (typeof source === \"string\" && HEAVY_LIBRARIES.has(source)) {\n context.report({\n node,\n message: `\"${source}\" is a heavy library — use React.lazy() or next/dynamic for code splitting`,\n });\n }\n },\n }),\n};\n\nexport const useLazyMotion: Rule = {\n create: (context: RuleContext) => ({\n ImportDeclaration(node: EsTreeNode) {\n const source = node.source?.value;\n if (source !== \"framer-motion\" && source !== \"motion/react\") return;\n\n const hasFullMotionImport = node.specifiers?.some(\n (specifier: EsTreeNode) =>\n specifier.type === \"ImportSpecifier\" && specifier.imported?.name === \"motion\",\n );\n\n if (hasFullMotionImport) {\n context.report({\n node,\n message: 'Import \"m\" with LazyMotion instead of \"motion\" — saves ~30kb in bundle size',\n });\n }\n },\n }),\n};\n\nexport const noUndeferredThirdParty: Rule = {\n create: (context: RuleContext) => ({\n JSXOpeningElement(node: EsTreeNode) {\n if (node.name?.type !== \"JSXIdentifier\" || node.name.name !== \"script\") return;\n const attributes = node.attributes ?? [];\n if (!findJsxAttribute(attributes, \"src\")) return;\n\n if (!hasJsxAttribute(attributes, \"defer\") && !hasJsxAttribute(attributes, \"async\")) {\n context.report({\n node,\n message:\n \"Synchronous <script> with src — add defer or async to avoid blocking first paint\",\n });\n }\n },\n }),\n};\n","import { PASSIVE_EVENT_NAMES } from \"../constants.js\";\nimport { isMemberProperty } from \"../helpers.js\";\nimport type { EsTreeNode, Rule, RuleContext } from \"../types.js\";\n\nexport const clientPassiveEventListeners: Rule = {\n create: (context: RuleContext) => ({\n CallExpression(node: EsTreeNode) {\n if (!isMemberProperty(node.callee, \"addEventListener\")) return;\n if (node.arguments?.length < 2) return;\n\n const eventNameNode = node.arguments[0];\n if (eventNameNode.type !== \"Literal\" || !PASSIVE_EVENT_NAMES.has(eventNameNode.value)) return;\n\n const eventName = eventNameNode.value;\n const optionsArgument = node.arguments[2];\n\n if (!optionsArgument) {\n context.report({\n node,\n message: `\"${eventName}\" listener without { passive: true } — blocks scrolling performance`,\n });\n return;\n }\n\n if (optionsArgument.type !== \"ObjectExpression\") return;\n\n const hasPassiveTrue = optionsArgument.properties?.some(\n (property: EsTreeNode) =>\n property.type === \"Property\" &&\n property.key?.type === \"Identifier\" &&\n property.key.name === \"passive\" &&\n property.value?.type === \"Literal\" &&\n property.value.value === true,\n );\n\n if (!hasPassiveTrue) {\n context.report({\n node,\n message: `\"${eventName}\" listener without { passive: true } — blocks scrolling performance`,\n });\n }\n },\n }),\n};\n","import { INDEX_PARAMETER_NAMES } from \"../constants.js\";\nimport { findJsxAttribute, walkAst } from \"../helpers.js\";\nimport type { EsTreeNode, Rule, RuleContext } from \"../types.js\";\n\nconst extractIndexName = (node: EsTreeNode): string | null => {\n if (node.type === \"Identifier\" && INDEX_PARAMETER_NAMES.has(node.name)) return node.name;\n\n if (node.type === \"TemplateLiteral\") {\n const indexExpression = node.expressions?.find(\n (expression: EsTreeNode) =>\n expression.type === \"Identifier\" && INDEX_PARAMETER_NAMES.has(expression.name),\n );\n if (indexExpression) return indexExpression.name;\n }\n\n if (\n node.type === \"CallExpression\" &&\n node.callee?.type === \"MemberExpression\" &&\n node.callee.object?.type === \"Identifier\" &&\n INDEX_PARAMETER_NAMES.has(node.callee.object.name) &&\n node.callee.property?.type === \"Identifier\" &&\n node.callee.property.name === \"toString\"\n )\n return node.callee.object.name;\n\n if (\n node.type === \"CallExpression\" &&\n node.callee?.type === \"Identifier\" &&\n node.callee.name === \"String\" &&\n node.arguments?.[0]?.type === \"Identifier\" &&\n INDEX_PARAMETER_NAMES.has(node.arguments[0].name)\n )\n return node.arguments[0].name;\n\n return null;\n};\n\nconst isInsideStaticPlaceholderMap = (node: EsTreeNode): boolean => {\n let current = node;\n while (current.parent) {\n current = current.parent;\n if (\n current.type === \"CallExpression\" &&\n current.callee?.type === \"MemberExpression\" &&\n current.callee.property?.name === \"map\"\n ) {\n const receiver = current.callee.object;\n if (receiver?.type === \"CallExpression\") {\n const callee = receiver.callee;\n if (\n callee?.type === \"MemberExpression\" &&\n callee.object?.type === \"Identifier\" &&\n callee.object.name === \"Array\" &&\n callee.property?.name === \"from\"\n )\n return true;\n }\n if (\n receiver?.type === \"NewExpression\" &&\n receiver.callee?.type === \"Identifier\" &&\n receiver.callee.name === \"Array\"\n )\n return true;\n }\n }\n return false;\n};\n\nexport const noArrayIndexAsKey: Rule = {\n create: (context: RuleContext) => ({\n JSXAttribute(node: EsTreeNode) {\n if (node.name?.type !== \"JSXIdentifier\" || node.name.name !== \"key\") return;\n if (!node.value || node.value.type !== \"JSXExpressionContainer\") return;\n\n const indexName = extractIndexName(node.value.expression);\n if (!indexName) return;\n if (isInsideStaticPlaceholderMap(node)) return;\n\n context.report({\n node,\n message: `Array index \"${indexName}\" used as key — causes bugs when list is reordered or filtered`,\n });\n },\n }),\n};\n\nconst PREVENT_DEFAULT_ELEMENTS: Record<string, string> = {\n form: \"onSubmit\",\n a: \"onClick\",\n};\n\nconst containsPreventDefaultCall = (node: EsTreeNode): boolean => {\n let didFindPreventDefault = false;\n walkAst(node, (child) => {\n if (didFindPreventDefault) return;\n if (\n child.type === \"CallExpression\" &&\n child.callee?.type === \"MemberExpression\" &&\n child.callee.property?.type === \"Identifier\" &&\n child.callee.property.name === \"preventDefault\"\n ) {\n didFindPreventDefault = true;\n }\n });\n return didFindPreventDefault;\n};\n\nexport const noPreventDefault: Rule = {\n create: (context: RuleContext) => ({\n JSXOpeningElement(node: EsTreeNode) {\n const elementName = node.name?.type === \"JSXIdentifier\" ? node.name.name : null;\n if (!elementName) return;\n\n const targetEventProp = PREVENT_DEFAULT_ELEMENTS[elementName];\n if (!targetEventProp) return;\n\n const eventAttribute = findJsxAttribute(node.attributes ?? [], targetEventProp);\n if (!eventAttribute?.value || eventAttribute.value.type !== \"JSXExpressionContainer\") return;\n\n const expression = eventAttribute.value.expression;\n if (\n expression?.type !== \"ArrowFunctionExpression\" &&\n expression?.type !== \"FunctionExpression\"\n )\n return;\n\n if (!containsPreventDefaultCall(expression)) return;\n\n const message =\n elementName === \"form\"\n ? \"preventDefault() on <form> onSubmit — form won't work without JavaScript. Consider using a server action for progressive enhancement\"\n : \"preventDefault() on <a> onClick — use a <button> or routing component instead\";\n\n context.report({ node, message });\n },\n }),\n};\n\nexport const renderingConditionalRender: Rule = {\n create: (context: RuleContext) => ({\n LogicalExpression(node: EsTreeNode) {\n if (node.operator !== \"&&\") return;\n\n const isRightJsx = node.right?.type === \"JSXElement\" || node.right?.type === \"JSXFragment\";\n if (!isRightJsx) return;\n\n if (\n node.left?.type === \"MemberExpression\" &&\n node.left.property?.type === \"Identifier\" &&\n node.left.property.name === \"length\"\n ) {\n context.report({\n node,\n message:\n \"Conditional rendering with .length can render '0' — use .length > 0 or Boolean(.length)\",\n });\n }\n },\n }),\n};\n","import {\n CHAINABLE_ITERATION_METHODS,\n DEEP_NESTING_THRESHOLD,\n DUPLICATE_STORAGE_READ_THRESHOLD,\n SEQUENTIAL_AWAIT_THRESHOLD,\n STORAGE_OBJECTS,\n TEST_FILE_PATTERN,\n} from \"../constants.js\";\nimport { createLoopAwareVisitors, isMemberProperty, walkAst } from \"../helpers.js\";\nimport type { EsTreeNode, Rule, RuleContext } from \"../types.js\";\n\nexport const jsCombineIterations: Rule = {\n create: (context: RuleContext) => ({\n CallExpression(node: EsTreeNode) {\n if (node.callee?.type !== \"MemberExpression\" || node.callee.property?.type !== \"Identifier\")\n return;\n\n const outerMethod = node.callee.property.name;\n if (!CHAINABLE_ITERATION_METHODS.has(outerMethod)) return;\n\n const innerCall = node.callee.object;\n if (\n innerCall?.type !== \"CallExpression\" ||\n innerCall.callee?.type !== \"MemberExpression\" ||\n innerCall.callee.property?.type !== \"Identifier\"\n )\n return;\n\n const innerMethod = innerCall.callee.property.name;\n if (!CHAINABLE_ITERATION_METHODS.has(innerMethod)) return;\n\n context.report({\n node,\n message: `.${innerMethod}().${outerMethod}() iterates the array twice — combine into a single loop with .reduce() or for...of`,\n });\n },\n }),\n};\n\nexport const jsTosortedImmutable: Rule = {\n create: (context: RuleContext) => ({\n CallExpression(node: EsTreeNode) {\n if (!isMemberProperty(node.callee, \"sort\")) return;\n\n const receiver = node.callee.object;\n if (\n receiver?.type === \"ArrayExpression\" &&\n receiver.elements?.length === 1 &&\n receiver.elements[0]?.type === \"SpreadElement\"\n ) {\n context.report({\n node,\n message: \"[...array].sort() — use array.toSorted() for immutable sorting (ES2023)\",\n });\n }\n },\n }),\n};\n\nexport const jsHoistRegexp: Rule = {\n create: (context: RuleContext) =>\n createLoopAwareVisitors({\n NewExpression(node: EsTreeNode) {\n if (node.callee?.type === \"Identifier\" && node.callee.name === \"RegExp\") {\n context.report({\n node,\n message: \"new RegExp() inside a loop — hoist to a module-level constant\",\n });\n }\n },\n }),\n};\n\nexport const jsMinMaxLoop: Rule = {\n create: (context: RuleContext) => ({\n MemberExpression(node: EsTreeNode) {\n if (!node.computed) return;\n\n const object = node.object;\n if (object?.type !== \"CallExpression\" || !isMemberProperty(object.callee, \"sort\")) return;\n\n const isFirstElement = node.property?.type === \"Literal\" && node.property.value === 0;\n const isLastElement =\n node.property?.type === \"BinaryExpression\" &&\n node.property.operator === \"-\" &&\n node.property.right?.type === \"Literal\" &&\n node.property.right.value === 1;\n\n if (isFirstElement || isLastElement) {\n const targetFunction = isFirstElement ? \"min\" : \"max\";\n context.report({\n node,\n message: `array.sort()[${isFirstElement ? \"0\" : \"length-1\"}] for min/max — use Math.${targetFunction}(...array) instead (O(n) vs O(n log n))`,\n });\n }\n },\n }),\n};\n\nexport const jsSetMapLookups: Rule = {\n create: (context: RuleContext) =>\n createLoopAwareVisitors({\n CallExpression(node: EsTreeNode) {\n if (node.callee?.type !== \"MemberExpression\" || node.callee.property?.type !== \"Identifier\")\n return;\n const methodName = node.callee.property.name;\n if (methodName === \"includes\" || methodName === \"indexOf\") {\n context.report({\n node,\n message: `array.${methodName}() in a loop is O(n) per call — convert to a Set for O(1) lookups`,\n });\n }\n },\n }),\n};\n\nexport const jsBatchDomCss: Rule = {\n create: (context: RuleContext) => {\n const isStyleAssignment = (node: EsTreeNode): boolean =>\n node.type === \"ExpressionStatement\" &&\n node.expression?.type === \"AssignmentExpression\" &&\n node.expression.left?.type === \"MemberExpression\" &&\n node.expression.left.object?.type === \"MemberExpression\" &&\n node.expression.left.object.property?.type === \"Identifier\" &&\n node.expression.left.object.property.name === \"style\";\n\n return {\n BlockStatement(node: EsTreeNode) {\n const statements = node.body ?? [];\n for (let statementIndex = 1; statementIndex < statements.length; statementIndex++) {\n if (\n isStyleAssignment(statements[statementIndex]) &&\n isStyleAssignment(statements[statementIndex - 1])\n ) {\n context.report({\n node: statements[statementIndex],\n message:\n \"Multiple sequential element.style assignments — batch with cssText or classList for fewer reflows\",\n });\n }\n }\n },\n };\n },\n};\n\nexport const jsIndexMaps: Rule = {\n create: (context: RuleContext) =>\n createLoopAwareVisitors({\n CallExpression(node: EsTreeNode) {\n if (node.callee?.type !== \"MemberExpression\" || node.callee.property?.type !== \"Identifier\")\n return;\n const methodName = node.callee.property.name;\n if (methodName === \"find\" || methodName === \"findIndex\") {\n context.report({\n node,\n message: `array.${methodName}() in a loop is O(n*m) — build a Map for O(1) lookups`,\n });\n }\n },\n }),\n};\n\nexport const jsCacheStorage: Rule = {\n create: (context: RuleContext) => {\n const storageReadCounts = new Map<string, number>();\n\n return {\n CallExpression(node: EsTreeNode) {\n if (!isMemberProperty(node.callee, \"getItem\")) return;\n if (\n node.callee.object?.type !== \"Identifier\" ||\n !STORAGE_OBJECTS.has(node.callee.object.name)\n )\n return;\n if (node.arguments?.[0]?.type !== \"Literal\") return;\n\n const storageKey = String(node.arguments[0].value);\n const readCount = (storageReadCounts.get(storageKey) ?? 0) + 1;\n storageReadCounts.set(storageKey, readCount);\n\n if (readCount === DUPLICATE_STORAGE_READ_THRESHOLD) {\n const storageName = node.callee.object.name;\n context.report({\n node,\n message: `${storageName}.getItem(\"${storageKey}\") called multiple times — cache the result in a variable`,\n });\n }\n },\n };\n },\n};\n\nexport const jsEarlyExit: Rule = {\n create: (context: RuleContext) => ({\n IfStatement(node: EsTreeNode) {\n if (node.consequent?.type !== \"BlockStatement\" || !node.consequent.body) return;\n\n let nestingDepth = 0;\n let currentBlock = node.consequent;\n while (currentBlock?.type === \"BlockStatement\" && currentBlock.body?.length === 1) {\n const innerStatement = currentBlock.body[0];\n if (innerStatement.type !== \"IfStatement\") break;\n nestingDepth++;\n currentBlock = innerStatement.consequent;\n }\n\n if (nestingDepth >= DEEP_NESTING_THRESHOLD) {\n context.report({\n node,\n message: `${nestingDepth + 1} levels of nested if statements — use early returns to flatten`,\n });\n }\n },\n }),\n};\n\nexport const asyncParallel: Rule = {\n create: (context: RuleContext) => {\n const filename = context.getFilename?.() ?? \"\";\n const isTestFile = TEST_FILE_PATTERN.test(filename);\n\n return {\n BlockStatement(node: EsTreeNode) {\n if (isTestFile) return;\n const consecutiveAwaitStatements: EsTreeNode[] = [];\n\n const flushConsecutiveAwaits = (): void => {\n if (consecutiveAwaitStatements.length >= SEQUENTIAL_AWAIT_THRESHOLD) {\n reportIfIndependent(consecutiveAwaitStatements, context);\n }\n consecutiveAwaitStatements.length = 0;\n };\n\n for (const statement of node.body ?? []) {\n const isAwaitStatement =\n (statement.type === \"VariableDeclaration\" &&\n statement.declarations?.length === 1 &&\n statement.declarations[0].init?.type === \"AwaitExpression\") ||\n (statement.type === \"ExpressionStatement\" &&\n statement.expression?.type === \"AwaitExpression\");\n\n if (isAwaitStatement) {\n consecutiveAwaitStatements.push(statement);\n } else {\n flushConsecutiveAwaits();\n }\n }\n flushConsecutiveAwaits();\n },\n };\n },\n};\n\nconst reportIfIndependent = (statements: EsTreeNode[], context: RuleContext): void => {\n const declaredNames = new Set<string>();\n\n for (const statement of statements) {\n if (statement.type !== \"VariableDeclaration\") continue;\n const declarator = statement.declarations[0];\n const awaitArgument = declarator.init?.argument;\n\n let referencesEarlierResult = false;\n walkAst(awaitArgument, (child: EsTreeNode) => {\n if (child.type === \"Identifier\" && declaredNames.has(child.name)) {\n referencesEarlierResult = true;\n }\n });\n\n if (referencesEarlierResult) return;\n\n if (declarator.id?.type === \"Identifier\") {\n declaredNames.add(declarator.id.name);\n }\n }\n\n context.report({\n node: statements[0],\n message: `${statements.length} sequential await statements that appear independent — use Promise.all() for parallel execution`,\n });\n};\n","import {\n APP_DIRECTORY_PATTERN,\n EFFECT_HOOK_NAMES,\n EXECUTABLE_SCRIPT_TYPES,\n GOOGLE_FONTS_PATTERN,\n INTERNAL_PAGE_PATH_PATTERN,\n MUTATING_ROUTE_SEGMENTS,\n NEXTJS_NAVIGATION_FUNCTIONS,\n OG_ROUTE_PATTERN,\n PAGE_FILE_PATTERN,\n PAGE_OR_LAYOUT_FILE_PATTERN,\n PAGES_DIRECTORY_PATTERN,\n POLYFILL_SCRIPT_PATTERN,\n ROUTE_HANDLER_FILE_PATTERN,\n} from \"../constants.js\";\nimport {\n containsFetchCall,\n findJsxAttribute,\n findSideEffect,\n getEffectCallback,\n hasDirective,\n hasJsxAttribute,\n isComponentAssignment,\n isHookCall,\n isMemberProperty,\n isUppercaseName,\n walkAst,\n} from \"../helpers.js\";\nimport type { EsTreeNode, Rule, RuleContext } from \"../types.js\";\n\nexport const nextjsNoImgElement: Rule = {\n create: (context: RuleContext) => {\n const filename = context.getFilename?.() ?? \"\";\n const isOgRoute = OG_ROUTE_PATTERN.test(filename);\n\n return {\n JSXOpeningElement(node: EsTreeNode) {\n if (isOgRoute) return;\n if (node.name?.type === \"JSXIdentifier\" && node.name.name === \"img\") {\n context.report({\n node,\n message:\n \"Use next/image instead of <img> — provides automatic optimization, lazy loading, and responsive srcset\",\n });\n }\n },\n };\n },\n};\n\nexport const nextjsAsyncClientComponent: Rule = {\n create: (context: RuleContext) => {\n let fileHasUseClient = false;\n\n return {\n Program(programNode: EsTreeNode) {\n fileHasUseClient = hasDirective(programNode, \"use client\");\n },\n FunctionDeclaration(node: EsTreeNode) {\n if (!fileHasUseClient || !node.async) return;\n if (!node.id?.name || !isUppercaseName(node.id.name)) return;\n context.report({\n node,\n message: `Async client component \"${node.id.name}\" — client components cannot be async`,\n });\n },\n VariableDeclarator(node: EsTreeNode) {\n if (!fileHasUseClient) return;\n if (!isComponentAssignment(node) || !node.init?.async) return;\n context.report({\n node,\n message: `Async client component \"${node.id.name}\" — client components cannot be async`,\n });\n },\n };\n },\n};\n\nexport const nextjsNoAElement: Rule = {\n create: (context: RuleContext) => ({\n JSXOpeningElement(node: EsTreeNode) {\n if (node.name?.type !== \"JSXIdentifier\" || node.name.name !== \"a\") return;\n\n const hrefAttribute = findJsxAttribute(node.attributes ?? [], \"href\");\n if (!hrefAttribute?.value) return;\n\n let hrefValue = null;\n if (hrefAttribute.value.type === \"Literal\") {\n hrefValue = hrefAttribute.value.value;\n } else if (\n hrefAttribute.value.type === \"JSXExpressionContainer\" &&\n hrefAttribute.value.expression?.type === \"Literal\"\n ) {\n hrefValue = hrefAttribute.value.expression.value;\n }\n\n if (typeof hrefValue === \"string\" && hrefValue.startsWith(\"/\")) {\n context.report({\n node,\n message:\n \"Use next/link instead of <a> for internal links — enables client-side navigation and prefetching\",\n });\n }\n },\n }),\n};\n\nexport const nextjsNoUseSearchParamsWithoutSuspense: Rule = {\n create: (context: RuleContext) => ({\n CallExpression(node: EsTreeNode) {\n if (!isHookCall(node, \"useSearchParams\")) return;\n context.report({\n node,\n message:\n \"useSearchParams() requires a <Suspense> boundary — without one, the entire page bails out to client-side rendering\",\n });\n },\n }),\n};\n\nexport const nextjsNoClientFetchForServerData: Rule = {\n create: (context: RuleContext) => {\n let fileHasUseClient = false;\n\n return {\n Program(programNode: EsTreeNode) {\n fileHasUseClient = hasDirective(programNode, \"use client\");\n },\n CallExpression(node: EsTreeNode) {\n if (!fileHasUseClient || !isHookCall(node, EFFECT_HOOK_NAMES)) return;\n\n const callback = getEffectCallback(node);\n if (!callback || !containsFetchCall(callback)) return;\n\n const filename = context.getFilename?.() ?? \"\";\n const isPageOrLayoutFile =\n PAGE_OR_LAYOUT_FILE_PATTERN.test(filename) || PAGES_DIRECTORY_PATTERN.test(filename);\n\n if (isPageOrLayoutFile) {\n context.report({\n node,\n message:\n \"useEffect + fetch in a page/layout — fetch data server-side with a server component instead\",\n });\n }\n },\n };\n },\n};\n\nexport const nextjsMissingMetadata: Rule = {\n create: (context: RuleContext) => ({\n Program(programNode: EsTreeNode) {\n const filename = context.getFilename?.() ?? \"\";\n if (!PAGE_FILE_PATTERN.test(filename)) return;\n if (INTERNAL_PAGE_PATH_PATTERN.test(filename)) return;\n\n const hasMetadataExport = programNode.body?.some((statement: EsTreeNode) => {\n if (statement.type !== \"ExportNamedDeclaration\") return false;\n const declaration = statement.declaration;\n if (declaration?.type === \"VariableDeclaration\") {\n return declaration.declarations?.some(\n (declarator: EsTreeNode) =>\n declarator.id?.type === \"Identifier\" &&\n (declarator.id.name === \"metadata\" || declarator.id.name === \"generateMetadata\"),\n );\n }\n if (declaration?.type === \"FunctionDeclaration\") {\n return declaration.id?.name === \"generateMetadata\";\n }\n return false;\n });\n\n if (!hasMetadataExport) {\n context.report({\n node: programNode,\n message: \"Page without metadata or generateMetadata export — hurts SEO\",\n });\n }\n },\n }),\n};\n\nconst describeClientSideNavigation = (node: EsTreeNode): string | null => {\n if (node.type === \"CallExpression\" && node.callee?.type === \"MemberExpression\") {\n const objectName = node.callee.object?.type === \"Identifier\" ? node.callee.object.name : null;\n const methodName =\n node.callee.property?.type === \"Identifier\" ? node.callee.property.name : null;\n if (objectName === \"router\" && (methodName === \"push\" || methodName === \"replace\")) {\n return `router.${methodName}() in useEffect — use redirect() from next/navigation or handle navigation in an event handler`;\n }\n }\n\n if (node.type === \"AssignmentExpression\" && node.left?.type === \"MemberExpression\") {\n const objectName = node.left.object?.type === \"Identifier\" ? node.left.object.name : null;\n const propertyName = node.left.property?.type === \"Identifier\" ? node.left.property.name : null;\n if (objectName === \"window\" && propertyName === \"location\") {\n return \"window.location assignment in useEffect — use redirect() from next/navigation or handle in middleware instead\";\n }\n if (objectName === \"location\" && propertyName === \"href\") {\n return \"location.href assignment in useEffect — use redirect() from next/navigation or handle in middleware instead\";\n }\n }\n\n return null;\n};\n\nexport const nextjsNoClientSideRedirect: Rule = {\n create: (context: RuleContext) => ({\n CallExpression(node: EsTreeNode) {\n if (!isHookCall(node, EFFECT_HOOK_NAMES)) return;\n const callback = getEffectCallback(node);\n if (!callback) return;\n\n walkAst(callback, (child: EsTreeNode) => {\n const navigationDescription = describeClientSideNavigation(child);\n if (navigationDescription) {\n context.report({\n node: child,\n message: navigationDescription,\n });\n }\n });\n },\n }),\n};\n\nexport const nextjsNoRedirectInTryCatch: Rule = {\n create: (context: RuleContext) => {\n let tryCatchDepth = 0;\n\n return {\n TryStatement() {\n tryCatchDepth++;\n },\n \"TryStatement:exit\"() {\n tryCatchDepth--;\n },\n CallExpression(node: EsTreeNode) {\n if (tryCatchDepth === 0) return;\n if (node.callee?.type !== \"Identifier\") return;\n if (!NEXTJS_NAVIGATION_FUNCTIONS.has(node.callee.name)) return;\n\n context.report({\n node,\n message: `${node.callee.name}() inside try-catch — this throws a special error Next.js handles internally. Move it outside the try block or use unstable_rethrow() in the catch`,\n });\n },\n };\n },\n};\n\nexport const nextjsImageMissingSizes: Rule = {\n create: (context: RuleContext) => ({\n JSXOpeningElement(node: EsTreeNode) {\n if (node.name?.type !== \"JSXIdentifier\" || node.name.name !== \"Image\") return;\n const attributes = node.attributes ?? [];\n if (!hasJsxAttribute(attributes, \"fill\")) return;\n if (hasJsxAttribute(attributes, \"sizes\")) return;\n\n context.report({\n node,\n message:\n \"next/image with fill but no sizes — the browser downloads the largest image. Add a sizes attribute for responsive behavior\",\n });\n },\n }),\n};\n\nexport const nextjsNoNativeScript: Rule = {\n create: (context: RuleContext) => ({\n JSXOpeningElement(node: EsTreeNode) {\n if (node.name?.type !== \"JSXIdentifier\" || node.name.name !== \"script\") return;\n\n const typeAttribute = findJsxAttribute(node.attributes ?? [], \"type\");\n const typeValue = typeAttribute?.value?.type === \"Literal\" ? typeAttribute.value.value : null;\n if (typeof typeValue === \"string\" && !EXECUTABLE_SCRIPT_TYPES.has(typeValue)) return;\n\n context.report({\n node,\n message:\n \"Use next/script <Script> instead of <script> — provides loading strategy optimization and deferred loading\",\n });\n },\n }),\n};\n\nexport const nextjsInlineScriptMissingId: Rule = {\n create: (context: RuleContext) => ({\n JSXOpeningElement(node: EsTreeNode) {\n if (node.name?.type !== \"JSXIdentifier\" || node.name.name !== \"Script\") return;\n const attributes = node.attributes ?? [];\n\n if (hasJsxAttribute(attributes, \"src\")) return;\n if (hasJsxAttribute(attributes, \"id\")) return;\n\n context.report({\n node,\n message:\n \"Inline <Script> without id — Next.js requires an id attribute to track inline scripts\",\n });\n },\n }),\n};\n\nexport const nextjsNoFontLink: Rule = {\n create: (context: RuleContext) => ({\n JSXOpeningElement(node: EsTreeNode) {\n if (node.name?.type !== \"JSXIdentifier\" || node.name.name !== \"link\") return;\n const attributes = node.attributes ?? [];\n\n const hrefAttribute = findJsxAttribute(attributes, \"href\");\n if (!hrefAttribute?.value) return;\n\n const hrefValue = hrefAttribute.value.type === \"Literal\" ? hrefAttribute.value.value : null;\n\n if (typeof hrefValue === \"string\" && GOOGLE_FONTS_PATTERN.test(hrefValue)) {\n context.report({\n node,\n message:\n \"Loading Google Fonts via <link> — use next/font instead for self-hosting, zero layout shift, and no render-blocking requests\",\n });\n }\n },\n }),\n};\n\nexport const nextjsNoCssLink: Rule = {\n create: (context: RuleContext) => ({\n JSXOpeningElement(node: EsTreeNode) {\n if (node.name?.type !== \"JSXIdentifier\" || node.name.name !== \"link\") return;\n const attributes = node.attributes ?? [];\n\n const relAttribute = findJsxAttribute(attributes, \"rel\");\n if (!relAttribute?.value) return;\n const relValue = relAttribute.value.type === \"Literal\" ? relAttribute.value.value : null;\n if (relValue !== \"stylesheet\") return;\n\n const hrefAttribute = findJsxAttribute(attributes, \"href\");\n if (!hrefAttribute?.value) return;\n const hrefValue = hrefAttribute.value.type === \"Literal\" ? hrefAttribute.value.value : null;\n if (typeof hrefValue === \"string\" && GOOGLE_FONTS_PATTERN.test(hrefValue)) return;\n\n context.report({\n node,\n message: '<link rel=\"stylesheet\"> tag — import CSS directly for bundling and optimization',\n });\n },\n }),\n};\n\nexport const nextjsNoPolyfillScript: Rule = {\n create: (context: RuleContext) => ({\n JSXOpeningElement(node: EsTreeNode) {\n if (node.name?.type !== \"JSXIdentifier\") return;\n if (node.name.name !== \"script\" && node.name.name !== \"Script\") return;\n\n const srcAttribute = findJsxAttribute(node.attributes ?? [], \"src\");\n if (!srcAttribute?.value) return;\n\n const srcValue = srcAttribute.value.type === \"Literal\" ? srcAttribute.value.value : null;\n\n if (typeof srcValue === \"string\" && POLYFILL_SCRIPT_PATTERN.test(srcValue)) {\n context.report({\n node,\n message:\n \"Polyfill CDN script — Next.js includes polyfills for fetch, Promise, Object.assign, and 50+ others automatically\",\n });\n }\n },\n }),\n};\n\nexport const nextjsNoHeadImport: Rule = {\n create: (context: RuleContext) => ({\n ImportDeclaration(node: EsTreeNode) {\n if (node.source?.value !== \"next/head\") return;\n\n const filename = context.getFilename?.() ?? \"\";\n if (!APP_DIRECTORY_PATTERN.test(filename)) return;\n\n context.report({\n node,\n message: \"next/head is not supported in the App Router — use the Metadata API instead\",\n });\n },\n }),\n};\n\nconst extractMutatingRouteSegment = (filename: string): string | null => {\n const segments = filename.split(\"/\");\n for (const segment of segments) {\n const cleaned = segment.replace(/^\\[.*\\]$/, \"\");\n if (MUTATING_ROUTE_SEGMENTS.has(cleaned)) return cleaned;\n }\n return null;\n};\n\nconst getExportedGetHandlerBody = (node: EsTreeNode): EsTreeNode | null => {\n if (node.type !== \"ExportNamedDeclaration\") return null;\n const declaration = node.declaration;\n if (!declaration) return null;\n\n if (declaration.type === \"FunctionDeclaration\" && declaration.id?.name === \"GET\") {\n return declaration.body;\n }\n\n if (declaration.type === \"VariableDeclaration\") {\n const declarator = declaration.declarations?.[0];\n if (\n declarator?.id?.type === \"Identifier\" &&\n declarator.id.name === \"GET\" &&\n declarator.init &&\n (declarator.init.type === \"ArrowFunctionExpression\" ||\n declarator.init.type === \"FunctionExpression\")\n ) {\n return declarator.init.body;\n }\n }\n\n return null;\n};\n\nexport const nextjsNoSideEffectInGetHandler: Rule = {\n create: (context: RuleContext) => ({\n ExportNamedDeclaration(node: EsTreeNode) {\n const filename = context.getFilename?.() ?? \"\";\n if (!ROUTE_HANDLER_FILE_PATTERN.test(filename)) return;\n\n const handlerBody = getExportedGetHandlerBody(node);\n if (!handlerBody) return;\n\n const mutatingSegment = extractMutatingRouteSegment(filename);\n if (mutatingSegment) {\n context.report({\n node,\n message: `GET handler on \"/${mutatingSegment}\" route — use POST to prevent CSRF and unintended prefetch triggers`,\n });\n return;\n }\n\n const sideEffect = findSideEffect(handlerBody);\n if (sideEffect) {\n context.report({\n node,\n message: `GET handler has side effects (${sideEffect}) — use POST to prevent CSRF and unintended prefetch triggers`,\n });\n }\n },\n }),\n};\n","import {\n ANIMATION_CALLBACK_NAMES,\n BLUR_VALUE_PATTERN,\n EFFECT_HOOK_NAMES,\n LARGE_BLUR_THRESHOLD_PX,\n LAYOUT_PROPERTIES,\n LOADING_STATE_PATTERN,\n MOTION_ANIMATE_PROPS,\n} from \"../constants.js\";\nimport {\n getEffectCallback,\n isComponentAssignment,\n isHookCall,\n isMemberProperty,\n isSetterCall,\n isSimpleExpression,\n isUppercaseName,\n walkAst,\n} from \"../helpers.js\";\nimport type { EsTreeNode, Rule, RuleContext } from \"../types.js\";\n\nconst isMemoCall = (node: EsTreeNode): boolean => {\n if (node.type !== \"CallExpression\") return false;\n if (node.callee?.type === \"Identifier\" && node.callee.name === \"memo\") return true;\n if (\n node.callee?.type === \"MemberExpression\" &&\n node.callee.object?.type === \"Identifier\" &&\n node.callee.object.name === \"React\" &&\n node.callee.property?.type === \"Identifier\" &&\n node.callee.property.name === \"memo\"\n )\n return true;\n return false;\n};\n\nconst isInlineReference = (node: EsTreeNode): string | null => {\n if (\n node.type === \"ArrowFunctionExpression\" ||\n node.type === \"FunctionExpression\" ||\n (node.type === \"CallExpression\" &&\n node.callee?.type === \"MemberExpression\" &&\n node.callee.property?.name === \"bind\")\n )\n return \"functions\";\n\n if (node.type === \"ObjectExpression\") return \"objects\";\n if (node.type === \"ArrayExpression\") return \"Arrays\";\n if (node.type === \"JSXElement\" || node.type === \"JSXFragment\") return \"JSX\";\n\n return null;\n};\n\nexport const noInlinePropOnMemoComponent: Rule = {\n create: (context: RuleContext) => {\n const memoizedComponentNames = new Set<string>();\n\n return {\n VariableDeclarator(node: EsTreeNode) {\n if (node.id?.type !== \"Identifier\" || !node.init) return;\n if (isMemoCall(node.init)) {\n memoizedComponentNames.add(node.id.name);\n }\n },\n ExportDefaultDeclaration(node: EsTreeNode) {\n if (node.declaration && isMemoCall(node.declaration)) {\n const innerArgument = node.declaration.arguments?.[0];\n if (innerArgument?.type === \"Identifier\") {\n memoizedComponentNames.add(innerArgument.name);\n }\n }\n },\n JSXAttribute(node: EsTreeNode) {\n if (!node.value || node.value.type !== \"JSXExpressionContainer\") return;\n\n const openingElement = node.parent;\n if (!openingElement || openingElement.type !== \"JSXOpeningElement\") return;\n\n let elementName: string | null = null;\n if (openingElement.name?.type === \"JSXIdentifier\") {\n elementName = openingElement.name.name;\n }\n if (!elementName || !memoizedComponentNames.has(elementName)) return;\n\n const propType = isInlineReference(node.value.expression);\n if (propType) {\n context.report({\n node: node.value.expression,\n message: `JSX attribute values should not contain ${propType} created in the same scope — ${elementName} is wrapped in memo(), so new references cause unnecessary re-renders`,\n });\n }\n },\n };\n },\n};\n\nexport const noUsememoSimpleExpression: Rule = {\n create: (context: RuleContext) => ({\n CallExpression(node: EsTreeNode) {\n if (!isHookCall(node, \"useMemo\")) return;\n\n const callback = node.arguments?.[0];\n if (!callback) return;\n if (callback.type !== \"ArrowFunctionExpression\" && callback.type !== \"FunctionExpression\")\n return;\n\n let returnExpression = null;\n if (callback.body?.type !== \"BlockStatement\") {\n returnExpression = callback.body;\n } else if (\n callback.body.body?.length === 1 &&\n callback.body.body[0].type === \"ReturnStatement\"\n ) {\n returnExpression = callback.body.body[0].argument;\n }\n\n if (returnExpression && isSimpleExpression(returnExpression)) {\n context.report({\n node,\n message:\n \"useMemo wrapping a trivially cheap expression — memo overhead exceeds the computation\",\n });\n }\n },\n }),\n};\n\nconst isMotionElement = (attributeNode: EsTreeNode): boolean => {\n const openingElement = attributeNode.parent;\n if (!openingElement || openingElement.type !== \"JSXOpeningElement\") return false;\n\n const elementName = openingElement.name;\n if (\n elementName?.type === \"JSXMemberExpression\" &&\n elementName.object?.type === \"JSXIdentifier\" &&\n (elementName.object.name === \"motion\" || elementName.object.name === \"m\")\n )\n return true;\n\n if (elementName?.type === \"JSXIdentifier\" && elementName.name.startsWith(\"Motion\")) return true;\n\n return false;\n};\n\nexport const noLayoutPropertyAnimation: Rule = {\n create: (context: RuleContext) => ({\n JSXAttribute(node: EsTreeNode) {\n if (node.name?.type !== \"JSXIdentifier\" || !MOTION_ANIMATE_PROPS.has(node.name.name)) return;\n if (!node.value || node.value.type !== \"JSXExpressionContainer\") return;\n if (isMotionElement(node)) return;\n\n const expression = node.value.expression;\n if (expression?.type !== \"ObjectExpression\") return;\n\n for (const property of expression.properties ?? []) {\n if (property.type !== \"Property\") continue;\n let propertyName = null;\n if (property.key?.type === \"Identifier\") {\n propertyName = property.key.name;\n } else if (property.key?.type === \"Literal\") {\n propertyName = property.key.value;\n }\n\n if (propertyName && LAYOUT_PROPERTIES.has(propertyName)) {\n context.report({\n node: property,\n message: `Animating layout property \"${propertyName}\" triggers layout recalculation every frame — use transform/scale or the layout prop`,\n });\n }\n }\n },\n }),\n};\n\nexport const noTransitionAll: Rule = {\n create: (context: RuleContext) => ({\n JSXAttribute(node: EsTreeNode) {\n if (node.name?.type !== \"JSXIdentifier\" || node.name.name !== \"style\") return;\n if (node.value?.type !== \"JSXExpressionContainer\") return;\n\n const expression = node.value.expression;\n if (expression?.type !== \"ObjectExpression\") return;\n\n for (const property of expression.properties ?? []) {\n if (property.type !== \"Property\") continue;\n const key = property.key?.type === \"Identifier\" ? property.key.name : null;\n if (key !== \"transition\") continue;\n\n if (\n property.value?.type === \"Literal\" &&\n typeof property.value.value === \"string\" &&\n property.value.value.startsWith(\"all\")\n ) {\n context.report({\n node: property,\n message:\n 'transition: \"all\" animates every property including layout — list only the properties you animate',\n });\n }\n }\n },\n }),\n};\n\nexport const noGlobalCssVariableAnimation: Rule = {\n create: (context: RuleContext) => ({\n CallExpression(node: EsTreeNode) {\n if (node.callee?.type !== \"Identifier\") return;\n if (!ANIMATION_CALLBACK_NAMES.has(node.callee.name)) return;\n\n const callback = node.arguments?.[0];\n if (!callback) return;\n\n const calleeName = node.callee.name;\n walkAst(callback, (child: EsTreeNode) => {\n if (child.type !== \"CallExpression\") return;\n if (!isMemberProperty(child.callee, \"setProperty\")) return;\n if (child.arguments?.[0]?.type !== \"Literal\") return;\n\n const variableName = child.arguments[0].value;\n if (typeof variableName !== \"string\" || !variableName.startsWith(\"--\")) return;\n\n context.report({\n node: child,\n message: `CSS variable \"${variableName}\" updated in ${calleeName} — forces style recalculation on all inheriting elements every frame`,\n });\n });\n },\n }),\n};\n\nexport const noLargeAnimatedBlur: Rule = {\n create: (context: RuleContext) => ({\n JSXAttribute(node: EsTreeNode) {\n if (node.name?.type !== \"JSXIdentifier\") return;\n if (node.name.name !== \"style\" && !MOTION_ANIMATE_PROPS.has(node.name.name)) return;\n if (node.value?.type !== \"JSXExpressionContainer\") return;\n\n const expression = node.value.expression;\n if (expression?.type !== \"ObjectExpression\") return;\n\n for (const property of expression.properties ?? []) {\n if (property.type !== \"Property\") continue;\n const key = property.key?.type === \"Identifier\" ? property.key.name : null;\n if (key !== \"filter\" && key !== \"backdropFilter\" && key !== \"WebkitBackdropFilter\")\n continue;\n if (property.value?.type !== \"Literal\" || typeof property.value.value !== \"string\")\n continue;\n\n const match = BLUR_VALUE_PATTERN.exec(property.value.value);\n if (!match) continue;\n\n const blurRadius = Number.parseFloat(match[1]);\n if (blurRadius > LARGE_BLUR_THRESHOLD_PX) {\n context.report({\n node: property,\n message: `blur(${blurRadius}px) is expensive — cost escalates with radius and layer size, can exceed GPU memory on mobile`,\n });\n }\n }\n },\n }),\n};\n\nexport const noScaleFromZero: Rule = {\n create: (context: RuleContext) => ({\n JSXAttribute(node: EsTreeNode) {\n if (node.name?.type !== \"JSXIdentifier\") return;\n if (node.name.name !== \"initial\" && node.name.name !== \"exit\") return;\n if (node.value?.type !== \"JSXExpressionContainer\") return;\n\n const expression = node.value.expression;\n if (expression?.type !== \"ObjectExpression\") return;\n\n for (const property of expression.properties ?? []) {\n if (property.type !== \"Property\") continue;\n const key = property.key?.type === \"Identifier\" ? property.key.name : null;\n if (key !== \"scale\") continue;\n\n if (property.value?.type === \"Literal\" && property.value.value === 0) {\n context.report({\n node: property,\n message:\n \"scale: 0 makes elements appear from nowhere — use scale: 0.95 with opacity: 0 for natural entrance\",\n });\n }\n }\n },\n }),\n};\n\nexport const noPermanentWillChange: Rule = {\n create: (context: RuleContext) => ({\n JSXAttribute(node: EsTreeNode) {\n if (node.name?.type !== \"JSXIdentifier\" || node.name.name !== \"style\") return;\n if (node.value?.type !== \"JSXExpressionContainer\") return;\n\n const expression = node.value.expression;\n if (expression?.type !== \"ObjectExpression\") return;\n\n for (const property of expression.properties ?? []) {\n if (property.type !== \"Property\") continue;\n const key = property.key?.type === \"Identifier\" ? property.key.name : null;\n if (key !== \"willChange\") continue;\n\n context.report({\n node: property,\n message:\n \"Permanent will-change wastes GPU memory — apply only during active animation and remove after\",\n });\n }\n },\n }),\n};\n\nexport const rerenderMemoWithDefaultValue: Rule = {\n create: (context: RuleContext) => {\n const checkDefaultProps = (params: EsTreeNode[]): void => {\n for (const param of params) {\n if (param.type !== \"ObjectPattern\") continue;\n for (const property of param.properties ?? []) {\n if (property.type !== \"Property\" || property.value?.type !== \"AssignmentPattern\")\n continue;\n const defaultValue = property.value.right;\n if (defaultValue?.type === \"ObjectExpression\" && defaultValue.properties?.length === 0) {\n context.report({\n node: defaultValue,\n message:\n \"Default prop value {} creates a new object reference every render — extract to a module-level constant\",\n });\n }\n if (defaultValue?.type === \"ArrayExpression\" && defaultValue.elements?.length === 0) {\n context.report({\n node: defaultValue,\n message:\n \"Default prop value [] creates a new array reference every render — extract to a module-level constant\",\n });\n }\n }\n }\n };\n\n return {\n FunctionDeclaration(node: EsTreeNode) {\n if (!node.id?.name || !isUppercaseName(node.id.name)) return;\n checkDefaultProps(node.params ?? []);\n },\n VariableDeclarator(node: EsTreeNode) {\n if (!isComponentAssignment(node)) return;\n checkDefaultProps(node.init.params ?? []);\n },\n };\n },\n};\n\nexport const renderingAnimateSvgWrapper: Rule = {\n create: (context: RuleContext) => ({\n JSXOpeningElement(node: EsTreeNode) {\n if (node.name?.type !== \"JSXIdentifier\" || node.name.name !== \"svg\") return;\n\n const hasAnimationProp = node.attributes?.some(\n (attribute: EsTreeNode) =>\n attribute.type === \"JSXAttribute\" &&\n attribute.name?.type === \"JSXIdentifier\" &&\n MOTION_ANIMATE_PROPS.has(attribute.name.name),\n );\n\n if (hasAnimationProp) {\n context.report({\n node,\n message:\n \"Animation props directly on <svg> — wrap in a <div> or <motion.div> for better rendering performance\",\n });\n }\n },\n }),\n};\n\nexport const renderingUsetransitionLoading: Rule = {\n create: (context: RuleContext) => ({\n VariableDeclarator(node: EsTreeNode) {\n if (node.id?.type !== \"ArrayPattern\" || !node.id.elements?.length) return;\n if (!node.init || !isHookCall(node.init, \"useState\")) return;\n if (!node.init.arguments?.length) return;\n\n const initializer = node.init.arguments[0];\n if (initializer.type !== \"Literal\" || initializer.value !== false) return;\n\n const stateVariableName = node.id.elements[0]?.name;\n if (!stateVariableName || !LOADING_STATE_PATTERN.test(stateVariableName)) return;\n\n context.report({\n node: node.init,\n message: `useState for \"${stateVariableName}\" — if this guards a state transition (not an async fetch), consider useTransition instead`,\n });\n },\n }),\n};\n\nexport const renderingHydrationNoFlicker: Rule = {\n create: (context: RuleContext) => ({\n CallExpression(node: EsTreeNode) {\n if (!isHookCall(node, EFFECT_HOOK_NAMES) || node.arguments?.length < 2) return;\n\n const depsNode = node.arguments[1];\n if (depsNode.type !== \"ArrayExpression\" || depsNode.elements?.length !== 0) return;\n\n const callback = getEffectCallback(node);\n if (!callback) return;\n\n const bodyStatements =\n callback.body?.type === \"BlockStatement\" ? callback.body.body : [callback.body];\n if (!bodyStatements || bodyStatements.length !== 1) return;\n\n const soleStatement = bodyStatements[0];\n if (soleStatement?.type === \"ExpressionStatement\" && isSetterCall(soleStatement.expression)) {\n context.report({\n node,\n message:\n \"useEffect(setState, []) on mount causes a flash — consider useSyncExternalStore or suppressHydrationWarning\",\n });\n }\n },\n }),\n};\n","import {\n DEPRECATED_RN_MODULE_REPLACEMENTS,\n LEGACY_EXPO_PACKAGE_REPLACEMENTS,\n LEGACY_SHADOW_STYLE_PROPERTIES,\n RAW_TEXT_PREVIEW_MAX_CHARS,\n REACT_NATIVE_LIST_COMPONENTS,\n REACT_NATIVE_TEXT_COMPONENTS,\n REACT_NATIVE_TEXT_COMPONENT_KEYWORDS,\n} from \"../constants.js\";\nimport { hasDirective, isMemberProperty } from \"../helpers.js\";\nimport type { EsTreeNode, Rule, RuleContext } from \"../types.js\";\n\nconst resolveJsxElementName = (openingElement: EsTreeNode): string | null => {\n const elementName = openingElement?.name;\n if (!elementName) return null;\n if (elementName.type === \"JSXIdentifier\") return elementName.name;\n if (elementName.type === \"JSXMemberExpression\") return elementName.property?.name ?? null;\n return null;\n};\n\nconst truncateText = (text: string): string =>\n text.length > RAW_TEXT_PREVIEW_MAX_CHARS\n ? `${text.slice(0, RAW_TEXT_PREVIEW_MAX_CHARS)}...`\n : text;\n\nconst isRawTextContent = (child: EsTreeNode): boolean => {\n if (child.type === \"JSXText\") return Boolean(child.value?.trim());\n if (child.type !== \"JSXExpressionContainer\" || !child.expression) return false;\n\n const expression = child.expression;\n return (\n (expression.type === \"Literal\" &&\n (typeof expression.value === \"string\" || typeof expression.value === \"number\")) ||\n expression.type === \"TemplateLiteral\"\n );\n};\n\nconst getRawTextDescription = (child: EsTreeNode): string => {\n if (child.type === \"JSXText\") {\n return `\"${truncateText(child.value.trim())}\"`;\n }\n\n if (child.type === \"JSXExpressionContainer\" && child.expression) {\n const expression = child.expression;\n if (expression.type === \"Literal\" && typeof expression.value === \"string\") {\n return `\"${truncateText(expression.value)}\"`;\n }\n if (expression.type === \"Literal\" && typeof expression.value === \"number\") {\n return `{${expression.value}}`;\n }\n if (expression.type === \"TemplateLiteral\") return \"template literal\";\n }\n\n return \"text content\";\n};\n\nconst isTextHandlingComponent = (elementName: string): boolean => {\n if (REACT_NATIVE_TEXT_COMPONENTS.has(elementName)) return true;\n return [...REACT_NATIVE_TEXT_COMPONENT_KEYWORDS].some((keyword) => elementName.includes(keyword));\n};\n\nexport const rnNoRawText: Rule = {\n create: (context: RuleContext) => {\n let isDomComponentFile = false;\n\n return {\n Program(programNode: EsTreeNode) {\n isDomComponentFile = hasDirective(programNode, \"use dom\");\n },\n JSXElement(node: EsTreeNode) {\n if (isDomComponentFile) return;\n\n const elementName = resolveJsxElementName(node.openingElement);\n if (elementName && isTextHandlingComponent(elementName)) return;\n\n for (const child of node.children ?? []) {\n if (!isRawTextContent(child)) continue;\n\n context.report({\n node: child,\n message: `Raw ${getRawTextDescription(child)} outside a <Text> component — this will crash on React Native`,\n });\n }\n },\n };\n },\n};\n\nexport const rnNoDeprecatedModules: Rule = {\n create: (context: RuleContext) => ({\n ImportDeclaration(node: EsTreeNode) {\n if (node.source?.value !== \"react-native\") return;\n\n for (const specifier of node.specifiers ?? []) {\n if (specifier.type !== \"ImportSpecifier\") continue;\n const importedName = specifier.imported?.name;\n if (!importedName) continue;\n\n const replacement = DEPRECATED_RN_MODULE_REPLACEMENTS[importedName];\n if (!replacement) continue;\n\n context.report({\n node: specifier,\n message: `\"${importedName}\" was removed from react-native — use ${replacement} instead`,\n });\n }\n },\n }),\n};\n\nexport const rnNoLegacyExpoPackages: Rule = {\n create: (context: RuleContext) => ({\n ImportDeclaration(node: EsTreeNode) {\n const source = node.source?.value;\n if (typeof source !== \"string\") return;\n\n for (const [packageName, replacement] of Object.entries(LEGACY_EXPO_PACKAGE_REPLACEMENTS)) {\n if (source === packageName || source.startsWith(`${packageName}/`)) {\n context.report({\n node,\n message: `\"${packageName}\" is deprecated — use ${replacement}`,\n });\n return;\n }\n }\n },\n }),\n};\n\nexport const rnNoDimensionsGet: Rule = {\n create: (context: RuleContext) => ({\n CallExpression(node: EsTreeNode) {\n if (node.callee?.type !== \"MemberExpression\") return;\n if (node.callee.object?.type !== \"Identifier\" || node.callee.object.name !== \"Dimensions\")\n return;\n\n if (isMemberProperty(node.callee, \"get\")) {\n context.report({\n node,\n message:\n \"Dimensions.get() does not update on screen rotation or resize — use useWindowDimensions() for reactive layout\",\n });\n }\n\n if (isMemberProperty(node.callee, \"addEventListener\")) {\n context.report({\n node,\n message:\n \"Dimensions.addEventListener() was removed in React Native 0.72 — use useWindowDimensions() instead\",\n });\n }\n },\n }),\n};\n\nexport const rnNoInlineFlatlistRenderitem: Rule = {\n create: (context: RuleContext) => ({\n JSXAttribute(node: EsTreeNode) {\n if (node.name?.type !== \"JSXIdentifier\" || node.name.name !== \"renderItem\") return;\n if (!node.value || node.value.type !== \"JSXExpressionContainer\") return;\n\n const openingElement = node.parent;\n if (!openingElement || openingElement.type !== \"JSXOpeningElement\") return;\n\n const listComponentName = resolveJsxElementName(openingElement);\n if (!listComponentName || !REACT_NATIVE_LIST_COMPONENTS.has(listComponentName)) return;\n\n const expression = node.value.expression;\n if (\n expression?.type !== \"ArrowFunctionExpression\" &&\n expression?.type !== \"FunctionExpression\"\n )\n return;\n\n context.report({\n node: expression,\n message: `Inline renderItem on <${listComponentName}> creates a new function reference every render — extract to a named function or wrap in useCallback`,\n });\n },\n }),\n};\n\nconst reportLegacyShadowProperties = (objectExpression: EsTreeNode, context: RuleContext): void => {\n const legacyShadowPropertyNames: string[] = [];\n\n for (const property of objectExpression.properties ?? []) {\n if (property.type !== \"Property\") continue;\n const propertyName = property.key?.type === \"Identifier\" ? property.key.name : null;\n if (propertyName && LEGACY_SHADOW_STYLE_PROPERTIES.has(propertyName)) {\n legacyShadowPropertyNames.push(propertyName);\n }\n }\n\n if (legacyShadowPropertyNames.length === 0) return;\n\n const quotedPropertyNames = legacyShadowPropertyNames.map((name) => `\"${name}\"`).join(\", \");\n context.report({\n node: objectExpression,\n message: `Legacy shadow style${legacyShadowPropertyNames.length > 1 ? \"s\" : \"\"} ${quotedPropertyNames} — use boxShadow for cross-platform shadows on the new architecture`,\n });\n};\n\nexport const rnNoLegacyShadowStyles: Rule = {\n create: (context: RuleContext) => ({\n JSXAttribute(node: EsTreeNode) {\n if (node.name?.type !== \"JSXIdentifier\" || node.name.name !== \"style\") return;\n if (node.value?.type !== \"JSXExpressionContainer\") return;\n\n const expression = node.value.expression;\n\n if (expression?.type === \"ObjectExpression\") {\n reportLegacyShadowProperties(expression, context);\n } else if (expression?.type === \"ArrayExpression\") {\n for (const element of expression.elements ?? []) {\n if (element?.type === \"ObjectExpression\") {\n reportLegacyShadowProperties(element, context);\n }\n }\n }\n },\n CallExpression(node: EsTreeNode) {\n if (node.callee?.type !== \"MemberExpression\") return;\n if (node.callee.object?.type !== \"Identifier\" || node.callee.object.name !== \"StyleSheet\")\n return;\n if (!isMemberProperty(node.callee, \"create\")) return;\n\n const stylesArgument = node.arguments?.[0];\n if (stylesArgument?.type !== \"ObjectExpression\") return;\n\n for (const styleDefinition of stylesArgument.properties ?? []) {\n if (styleDefinition.type !== \"Property\") continue;\n if (styleDefinition.value?.type !== \"ObjectExpression\") continue;\n reportLegacyShadowProperties(styleDefinition.value, context);\n }\n },\n }),\n};\n\nexport const rnPreferReanimated: Rule = {\n create: (context: RuleContext) => ({\n ImportDeclaration(node: EsTreeNode) {\n if (node.source?.value !== \"react-native\") return;\n\n for (const specifier of node.specifiers ?? []) {\n if (specifier.type !== \"ImportSpecifier\") continue;\n if (specifier.imported?.name !== \"Animated\") continue;\n\n context.report({\n node: specifier,\n message:\n \"Animated from react-native runs animations on the JS thread — use react-native-reanimated for performant UI-thread animations\",\n });\n }\n },\n }),\n};\n\nexport const rnNoSingleElementStyleArray: Rule = {\n create: (context: RuleContext) => ({\n JSXAttribute(node: EsTreeNode) {\n const propName = node.name?.type === \"JSXIdentifier\" ? node.name.name : null;\n if (!propName) return;\n if (propName !== \"style\" && !propName.endsWith(\"Style\")) return;\n if (node.value?.type !== \"JSXExpressionContainer\") return;\n\n const expression = node.value.expression;\n if (expression?.type !== \"ArrayExpression\") return;\n if (expression.elements?.length !== 1) return;\n\n context.report({\n node: expression,\n message: `Single-element style array on \"${propName}\" — use ${propName}={value} instead of ${propName}={[value]} to avoid unnecessary array allocation`,\n });\n },\n }),\n};\n","import {\n SECRET_FALSE_POSITIVE_SUFFIXES,\n SECRET_MIN_LENGTH_CHARS,\n SECRET_PATTERNS,\n SECRET_VARIABLE_PATTERN,\n} from \"../constants.js\";\nimport type { EsTreeNode, Rule, RuleContext } from \"../types.js\";\n\nexport const noEval: Rule = {\n create: (context: RuleContext) => ({\n CallExpression(node: EsTreeNode) {\n if (node.callee?.type === \"Identifier\" && node.callee.name === \"eval\") {\n context.report({\n node,\n message: \"eval() is a code injection risk — avoid dynamic code execution\",\n });\n return;\n }\n\n if (\n node.callee?.type === \"Identifier\" &&\n (node.callee.name === \"setTimeout\" || node.callee.name === \"setInterval\") &&\n node.arguments?.[0]?.type === \"Literal\" &&\n typeof node.arguments[0].value === \"string\"\n ) {\n context.report({\n node,\n message: `${node.callee.name}() with string argument executes code dynamically — use a function instead`,\n });\n }\n },\n NewExpression(node: EsTreeNode) {\n if (node.callee?.type === \"Identifier\" && node.callee.name === \"Function\") {\n context.report({\n node,\n message: \"new Function() is a code injection risk — avoid dynamic code execution\",\n });\n }\n },\n }),\n};\n\nexport const noSecretsInClientCode: Rule = {\n create: (context: RuleContext) => ({\n VariableDeclarator(node: EsTreeNode) {\n if (node.id?.type !== \"Identifier\") return;\n if (node.init?.type !== \"Literal\" || typeof node.init.value !== \"string\") return;\n\n const variableName = node.id.name;\n const literalValue = node.init.value;\n\n const trailingSuffix = variableName.split(\"_\").pop()?.toLowerCase() ?? \"\";\n const isUiConstant = SECRET_FALSE_POSITIVE_SUFFIXES.has(trailingSuffix);\n\n if (\n SECRET_VARIABLE_PATTERN.test(variableName) &&\n !isUiConstant &&\n literalValue.length > SECRET_MIN_LENGTH_CHARS\n ) {\n context.report({\n node,\n message: `Possible hardcoded secret in \"${variableName}\" — use environment variables instead`,\n });\n return;\n }\n\n if (SECRET_PATTERNS.some((pattern) => pattern.test(literalValue))) {\n context.report({\n node,\n message: \"Hardcoded secret detected — use environment variables instead\",\n });\n }\n },\n }),\n};\n","import {\n AUTH_CHECK_LOOKAHEAD_STATEMENTS,\n AUTH_FUNCTION_NAMES,\n SERVER_ACTION_DIRECTORY_PATTERN,\n SERVER_ACTION_FILE_PATTERN,\n} from \"../constants.js\";\nimport { hasDirective, hasUseServerDirective, walkAst } from \"../helpers.js\";\nimport type { EsTreeNode, Rule, RuleContext } from \"../types.js\";\n\nconst containsAuthCheck = (statements: EsTreeNode[]): boolean => {\n let foundAuthCall = false;\n for (const statement of statements) {\n walkAst(statement, (child: EsTreeNode) => {\n if (foundAuthCall) return;\n let callNode: EsTreeNode | null = null;\n if (child.type === \"CallExpression\") {\n callNode = child;\n } else if (child.type === \"AwaitExpression\" && child.argument?.type === \"CallExpression\") {\n callNode = child.argument;\n }\n\n if (\n callNode?.callee?.type === \"Identifier\" &&\n AUTH_FUNCTION_NAMES.has(callNode.callee.name)\n ) {\n foundAuthCall = true;\n }\n });\n }\n return foundAuthCall;\n};\n\nexport const serverAuthActions: Rule = {\n create: (context: RuleContext) => {\n let fileHasUseServerDirective = false;\n\n return {\n Program(programNode: EsTreeNode) {\n fileHasUseServerDirective = hasDirective(programNode, \"use server\");\n },\n ExportNamedDeclaration(node: EsTreeNode) {\n const declaration = node.declaration;\n if (declaration?.type !== \"FunctionDeclaration\" || !declaration?.async) return;\n\n const isServerAction = fileHasUseServerDirective || hasUseServerDirective(declaration);\n if (!isServerAction) return;\n\n const firstStatements = (declaration.body?.body ?? []).slice(\n 0,\n AUTH_CHECK_LOOKAHEAD_STATEMENTS,\n );\n if (!containsAuthCheck(firstStatements)) {\n const functionName = declaration.id?.name ?? \"anonymous\";\n context.report({\n node: declaration.id ?? node,\n message: `Server action \"${functionName}\" — add auth check (auth(), getSession(), etc.) at the top`,\n });\n }\n },\n };\n },\n};\n\nexport const serverAfterNonblocking: Rule = {\n create: (context: RuleContext) => {\n let fileHasUseServerDirective = false;\n\n return {\n Program(programNode: EsTreeNode) {\n fileHasUseServerDirective = hasDirective(programNode, \"use server\");\n },\n CallExpression(node: EsTreeNode) {\n if (!fileHasUseServerDirective) return;\n if (node.callee?.type !== \"MemberExpression\") return;\n if (node.callee.property?.type !== \"Identifier\") return;\n\n const objectName =\n node.callee.object?.type === \"Identifier\" ? node.callee.object.name : null;\n if (!objectName) return;\n\n const methodName = node.callee.property.name;\n const isLoggingCall =\n (objectName === \"console\" &&\n (methodName === \"log\" || methodName === \"info\" || methodName === \"warn\")) ||\n (objectName === \"analytics\" &&\n (methodName === \"track\" || methodName === \"identify\" || methodName === \"page\"));\n if (!isLoggingCall) return;\n\n context.report({\n node,\n message: `${objectName}.${methodName}() in server action — use after() for non-blocking logging/analytics`,\n });\n },\n };\n },\n};\n","import {\n CASCADING_SET_STATE_THRESHOLD,\n EFFECT_HOOK_NAMES,\n HOOKS_WITH_DEPS,\n RELATED_USE_STATE_THRESHOLD,\n TRIVIAL_INITIALIZER_NAMES,\n} from \"../constants.js\";\nimport {\n containsFetchCall,\n countSetStateCalls,\n extractDestructuredPropNames,\n getCallbackStatements,\n getEffectCallback,\n isComponentAssignment,\n isHookCall,\n isSetterCall,\n isSetterIdentifier,\n isUppercaseName,\n walkAst,\n} from \"../helpers.js\";\nimport type { EsTreeNode, Rule, RuleContext } from \"../types.js\";\n\nexport const noDerivedStateEffect: Rule = {\n create: (context: RuleContext) => ({\n CallExpression(node: EsTreeNode) {\n if (!isHookCall(node, EFFECT_HOOK_NAMES) || node.arguments.length < 2) return;\n\n const callback = getEffectCallback(node);\n if (!callback) return;\n\n const depsNode = node.arguments[1];\n if (depsNode.type !== \"ArrayExpression\" || !depsNode.elements?.length) return;\n\n const dependencyNames = new Set(\n depsNode.elements\n .filter((element: EsTreeNode) => element?.type === \"Identifier\")\n .map((element: EsTreeNode) => element.name),\n );\n if (dependencyNames.size === 0) return;\n\n const statements = getCallbackStatements(callback);\n if (statements.length === 0) return;\n\n const containsOnlySetStateCalls = statements.every((statement: EsTreeNode) => {\n if (statement.type !== \"ExpressionStatement\") return false;\n return isSetterCall(statement.expression);\n });\n if (!containsOnlySetStateCalls) return;\n\n let allArgumentsDeriveFromDeps = true;\n let hasAnyDependencyReference = false;\n for (const statement of statements) {\n const setStateArguments = statement.expression.arguments;\n if (!setStateArguments?.length) continue;\n\n const referencedIdentifiers: string[] = [];\n walkAst(setStateArguments[0], (child: EsTreeNode) => {\n if (child.type === \"Identifier\") referencedIdentifiers.push(child.name);\n });\n\n const nonSetterIdentifiers = referencedIdentifiers.filter(\n (name) => !isSetterIdentifier(name),\n );\n\n if (nonSetterIdentifiers.some((name) => dependencyNames.has(name))) {\n hasAnyDependencyReference = true;\n }\n\n if (nonSetterIdentifiers.some((name) => !dependencyNames.has(name))) {\n allArgumentsDeriveFromDeps = false;\n break;\n }\n }\n\n if (allArgumentsDeriveFromDeps) {\n context.report({\n node,\n message: hasAnyDependencyReference\n ? \"Derived state in useEffect — compute during render instead\"\n : \"State reset in useEffect — use a key prop to reset component state when props change\",\n });\n }\n },\n }),\n};\n\nexport const noFetchInEffect: Rule = {\n create: (context: RuleContext) => ({\n CallExpression(node: EsTreeNode) {\n if (!isHookCall(node, EFFECT_HOOK_NAMES)) return;\n const callback = getEffectCallback(node);\n if (!callback) return;\n\n if (containsFetchCall(callback)) {\n context.report({\n node,\n message:\n \"fetch() inside useEffect — use a data fetching library (react-query, SWR) or server component\",\n });\n }\n },\n }),\n};\n\nexport const noCascadingSetState: Rule = {\n create: (context: RuleContext) => ({\n CallExpression(node: EsTreeNode) {\n if (!isHookCall(node, EFFECT_HOOK_NAMES)) return;\n const callback = getEffectCallback(node);\n if (!callback) return;\n\n const setStateCallCount = countSetStateCalls(callback);\n if (setStateCallCount >= CASCADING_SET_STATE_THRESHOLD) {\n context.report({\n node,\n message: `${setStateCallCount} setState calls in a single useEffect — consider using useReducer or deriving state`,\n });\n }\n },\n }),\n};\n\nexport const noEffectEventHandler: Rule = {\n create: (context: RuleContext) => ({\n CallExpression(node: EsTreeNode) {\n if (!isHookCall(node, EFFECT_HOOK_NAMES) || node.arguments.length < 2) return;\n\n const callback = getEffectCallback(node);\n if (!callback) return;\n\n const depsNode = node.arguments[1];\n if (depsNode.type !== \"ArrayExpression\" || !depsNode.elements?.length) return;\n\n const dependencyNames = new Set(\n depsNode.elements\n .filter((element: EsTreeNode) => element?.type === \"Identifier\")\n .map((element: EsTreeNode) => element.name),\n );\n\n const statements = getCallbackStatements(callback);\n if (statements.length !== 1) return;\n\n const soleStatement = statements[0];\n if (\n soleStatement.type === \"IfStatement\" &&\n soleStatement.test?.type === \"Identifier\" &&\n dependencyNames.has(soleStatement.test.name)\n ) {\n context.report({\n node,\n message:\n \"useEffect simulating an event handler — move logic to an actual event handler instead\",\n });\n }\n },\n }),\n};\n\nexport const noDerivedUseState: Rule = {\n create: (context: RuleContext) => {\n const componentPropNames = new Set<string>();\n\n return {\n FunctionDeclaration(node: EsTreeNode) {\n if (!node.id?.name || !isUppercaseName(node.id.name)) return;\n for (const name of extractDestructuredPropNames(node.params ?? [])) {\n componentPropNames.add(name);\n }\n },\n VariableDeclarator(node: EsTreeNode) {\n if (!isComponentAssignment(node)) return;\n for (const name of extractDestructuredPropNames(node.init?.params ?? [])) {\n componentPropNames.add(name);\n }\n },\n CallExpression(node: EsTreeNode) {\n if (!isHookCall(node, \"useState\") || !node.arguments?.length) return;\n const initializer = node.arguments[0];\n if (initializer.type !== \"Identifier\") return;\n\n if (componentPropNames.has(initializer.name)) {\n context.report({\n node,\n message: `useState initialized from prop \"${initializer.name}\" — if this value should stay in sync with the prop, derive it during render instead`,\n });\n }\n },\n };\n },\n};\n\nexport const preferUseReducer: Rule = {\n create: (context: RuleContext) => {\n const reportExcessiveUseState = (body: EsTreeNode, componentName: string): void => {\n if (body.type !== \"BlockStatement\") return;\n let useStateCount = 0;\n for (const statement of body.body ?? []) {\n if (statement.type !== \"VariableDeclaration\") continue;\n for (const declarator of statement.declarations ?? []) {\n if (isHookCall(declarator.init, \"useState\")) useStateCount++;\n }\n }\n if (useStateCount >= RELATED_USE_STATE_THRESHOLD) {\n context.report({\n node: body,\n message: `Component \"${componentName}\" has ${useStateCount} useState calls — consider useReducer for related state`,\n });\n }\n };\n\n return {\n FunctionDeclaration(node: EsTreeNode) {\n if (!node.id?.name || !isUppercaseName(node.id.name)) return;\n reportExcessiveUseState(node.body, node.id.name);\n },\n VariableDeclarator(node: EsTreeNode) {\n if (!isComponentAssignment(node)) return;\n reportExcessiveUseState(node.init.body, node.id.name);\n },\n };\n },\n};\n\nexport const rerenderLazyStateInit: Rule = {\n create: (context: RuleContext) => ({\n CallExpression(node: EsTreeNode) {\n if (!isHookCall(node, \"useState\") || !node.arguments?.length) return;\n const initializer = node.arguments[0];\n if (initializer.type !== \"CallExpression\") return;\n\n const calleeName =\n initializer.callee?.type === \"Identifier\"\n ? initializer.callee.name\n : (initializer.callee?.property?.name ?? \"fn\");\n\n if (TRIVIAL_INITIALIZER_NAMES.has(calleeName)) return;\n\n context.report({\n node: initializer,\n message: `useState(${calleeName}()) calls initializer on every render — use useState(() => ${calleeName}()) for lazy initialization`,\n });\n },\n }),\n};\n\nexport const rerenderFunctionalSetstate: Rule = {\n create: (context: RuleContext) => ({\n CallExpression(node: EsTreeNode) {\n if (!isSetterCall(node)) return;\n if (!node.arguments?.length) return;\n\n const calleeName = node.callee.name;\n const argument = node.arguments[0];\n if (\n argument.type === \"BinaryExpression\" &&\n (argument.operator === \"+\" || argument.operator === \"-\") &&\n argument.left?.type === \"Identifier\"\n ) {\n context.report({\n node,\n message: `${calleeName}(${argument.left.name} ${argument.operator} ...) — use functional update to avoid stale closures`,\n });\n }\n },\n }),\n};\n\nexport const rerenderDependencies: Rule = {\n create: (context: RuleContext) => ({\n CallExpression(node: EsTreeNode) {\n if (!isHookCall(node, HOOKS_WITH_DEPS) || node.arguments.length < 2) return;\n const depsNode = node.arguments[1];\n if (depsNode.type !== \"ArrayExpression\") return;\n\n for (const element of depsNode.elements ?? []) {\n if (!element) continue;\n if (element.type === \"ObjectExpression\") {\n context.report({\n node: element,\n message:\n \"Object literal in useEffect deps — creates new reference every render, causing infinite re-runs\",\n });\n }\n if (element.type === \"ArrayExpression\") {\n context.report({\n node: element,\n message:\n \"Array literal in useEffect deps — creates new reference every render, causing infinite re-runs\",\n });\n }\n }\n },\n }),\n};\n","import {\n noGiantComponent,\n noNestedComponentDefinition,\n noRenderInRender,\n} from \"./rules/architecture.js\";\nimport {\n noBarrelImport,\n noFullLodashImport,\n noMoment,\n noUndeferredThirdParty,\n preferDynamicImport,\n useLazyMotion,\n} from \"./rules/bundle-size.js\";\nimport { clientPassiveEventListeners } from \"./rules/client.js\";\nimport {\n noArrayIndexAsKey,\n noPreventDefault,\n renderingConditionalRender,\n} from \"./rules/correctness.js\";\nimport {\n asyncParallel,\n jsBatchDomCss,\n jsCacheStorage,\n jsCombineIterations,\n jsEarlyExit,\n jsHoistRegexp,\n jsIndexMaps,\n jsMinMaxLoop,\n jsSetMapLookups,\n jsTosortedImmutable,\n} from \"./rules/js-performance.js\";\nimport {\n nextjsAsyncClientComponent,\n nextjsImageMissingSizes,\n nextjsInlineScriptMissingId,\n nextjsMissingMetadata,\n nextjsNoAElement,\n nextjsNoClientFetchForServerData,\n nextjsNoClientSideRedirect,\n nextjsNoCssLink,\n nextjsNoFontLink,\n nextjsNoHeadImport,\n nextjsNoImgElement,\n nextjsNoNativeScript,\n nextjsNoPolyfillScript,\n nextjsNoRedirectInTryCatch,\n nextjsNoSideEffectInGetHandler,\n nextjsNoUseSearchParamsWithoutSuspense,\n} from \"./rules/nextjs.js\";\nimport {\n noGlobalCssVariableAnimation,\n noLargeAnimatedBlur,\n noLayoutPropertyAnimation,\n noPermanentWillChange,\n noScaleFromZero,\n noTransitionAll,\n noUsememoSimpleExpression,\n renderingAnimateSvgWrapper,\n noInlinePropOnMemoComponent,\n renderingHydrationNoFlicker,\n rerenderMemoWithDefaultValue,\n} from \"./rules/performance.js\";\nimport {\n rnNoRawText,\n rnNoDeprecatedModules,\n rnNoLegacyExpoPackages,\n rnNoDimensionsGet,\n rnNoInlineFlatlistRenderitem,\n rnNoLegacyShadowStyles,\n rnPreferReanimated,\n rnNoSingleElementStyleArray,\n} from \"./rules/react-native.js\";\nimport { noEval, noSecretsInClientCode } from \"./rules/security.js\";\nimport { serverAfterNonblocking, serverAuthActions } from \"./rules/server.js\";\nimport {\n noCascadingSetState,\n noDerivedStateEffect,\n noDerivedUseState,\n noEffectEventHandler,\n noFetchInEffect,\n preferUseReducer,\n rerenderDependencies,\n rerenderFunctionalSetstate,\n rerenderLazyStateInit,\n} from \"./rules/state-and-effects.js\";\nimport type { RulePlugin } from \"./types.js\";\n\nconst plugin: RulePlugin = {\n meta: { name: \"react-doctor\" },\n rules: {\n \"no-derived-state-effect\": noDerivedStateEffect,\n \"no-fetch-in-effect\": noFetchInEffect,\n \"no-cascading-set-state\": noCascadingSetState,\n \"no-effect-event-handler\": noEffectEventHandler,\n \"no-derived-useState\": noDerivedUseState,\n \"prefer-useReducer\": preferUseReducer,\n \"rerender-lazy-state-init\": rerenderLazyStateInit,\n \"rerender-functional-setstate\": rerenderFunctionalSetstate,\n \"rerender-dependencies\": rerenderDependencies,\n\n \"no-giant-component\": noGiantComponent,\n \"no-render-in-render\": noRenderInRender,\n \"no-nested-component-definition\": noNestedComponentDefinition,\n\n \"no-usememo-simple-expression\": noUsememoSimpleExpression,\n \"no-layout-property-animation\": noLayoutPropertyAnimation,\n \"rerender-memo-with-default-value\": rerenderMemoWithDefaultValue,\n \"rendering-animate-svg-wrapper\": renderingAnimateSvgWrapper,\n \"no-inline-prop-on-memo-component\": noInlinePropOnMemoComponent,\n \"rendering-hydration-no-flicker\": renderingHydrationNoFlicker,\n\n \"no-transition-all\": noTransitionAll,\n \"no-global-css-variable-animation\": noGlobalCssVariableAnimation,\n \"no-large-animated-blur\": noLargeAnimatedBlur,\n \"no-scale-from-zero\": noScaleFromZero,\n \"no-permanent-will-change\": noPermanentWillChange,\n\n \"no-eval\": noEval,\n \"no-secrets-in-client-code\": noSecretsInClientCode,\n\n \"no-barrel-import\": noBarrelImport,\n \"no-full-lodash-import\": noFullLodashImport,\n \"no-moment\": noMoment,\n \"prefer-dynamic-import\": preferDynamicImport,\n \"use-lazy-motion\": useLazyMotion,\n \"no-undeferred-third-party\": noUndeferredThirdParty,\n\n \"no-array-index-as-key\": noArrayIndexAsKey,\n \"rendering-conditional-render\": renderingConditionalRender,\n \"no-prevent-default\": noPreventDefault,\n\n \"nextjs-no-img-element\": nextjsNoImgElement,\n \"nextjs-async-client-component\": nextjsAsyncClientComponent,\n \"nextjs-no-a-element\": nextjsNoAElement,\n \"nextjs-no-use-search-params-without-suspense\": nextjsNoUseSearchParamsWithoutSuspense,\n \"nextjs-no-client-fetch-for-server-data\": nextjsNoClientFetchForServerData,\n \"nextjs-missing-metadata\": nextjsMissingMetadata,\n \"nextjs-no-client-side-redirect\": nextjsNoClientSideRedirect,\n \"nextjs-no-redirect-in-try-catch\": nextjsNoRedirectInTryCatch,\n \"nextjs-image-missing-sizes\": nextjsImageMissingSizes,\n \"nextjs-no-native-script\": nextjsNoNativeScript,\n \"nextjs-inline-script-missing-id\": nextjsInlineScriptMissingId,\n \"nextjs-no-font-link\": nextjsNoFontLink,\n \"nextjs-no-css-link\": nextjsNoCssLink,\n \"nextjs-no-polyfill-script\": nextjsNoPolyfillScript,\n \"nextjs-no-head-import\": nextjsNoHeadImport,\n \"nextjs-no-side-effect-in-get-handler\": nextjsNoSideEffectInGetHandler,\n\n \"server-auth-actions\": serverAuthActions,\n \"server-after-nonblocking\": serverAfterNonblocking,\n\n \"client-passive-event-listeners\": clientPassiveEventListeners,\n\n \"js-combine-iterations\": jsCombineIterations,\n \"js-tosorted-immutable\": jsTosortedImmutable,\n \"js-hoist-regexp\": jsHoistRegexp,\n \"js-min-max-loop\": jsMinMaxLoop,\n \"js-set-map-lookups\": jsSetMapLookups,\n \"js-batch-dom-css\": jsBatchDomCss,\n \"js-index-maps\": jsIndexMaps,\n \"js-cache-storage\": jsCacheStorage,\n \"js-early-exit\": jsEarlyExit,\n \"async-parallel\": asyncParallel,\n\n \"rn-no-raw-text\": rnNoRawText,\n \"rn-no-deprecated-modules\": rnNoDeprecatedModules,\n \"rn-no-legacy-expo-packages\": rnNoLegacyExpoPackages,\n \"rn-no-dimensions-get\": rnNoDimensionsGet,\n \"rn-no-inline-flatlist-renderitem\": rnNoInlineFlatlistRenderitem,\n \"rn-no-legacy-shadow-styles\": rnNoLegacyShadowStyles,\n \"rn-prefer-reanimated\": rnPreferReanimated,\n \"rn-no-single-element-style-array\": rnNoSingleElementStyleArray,\n },\n};\n\nexport default plugin;\n"],"mappings":";AAAA,MAAa,iCAAiC;AAC9C,MAAa,gCAAgC;AAC7C,MAAa,8BAA8B;AAC3C,MAAa,yBAAyB;AACtC,MAAa,mCAAmC;AAChD,MAAa,6BAA6B;AAC1C,MAAa,0BAA0B;AACvC,MAAa,kCAAkC;AAE/C,MAAa,oBAAoB,IAAI,IAAI;CACvC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;AAEF,MAAa,uBAAuB,IAAI,IAAI;CAC1C;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;AAEF,MAAa,kBAAkB,IAAI,IAAI;CACrC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;AAEF,MAAa,qBAAqB,IAAI,IAAI,CAAC,QAAQ,CAAC;AACpD,MAAa,uBAAuB,IAAI,IAAI;CAAC;CAAS;CAAM;CAAM,CAAC;AACnE,MAAa,wBAAwB,IAAI,IAAI;CAAC;CAAS;CAAO;CAAI,CAAC;AACnE,MAAa,wBAAwB;CACnC;CACA;CACA;CACA;CACA;CACD;AACD,MAAa,sBAAsB,IAAI,IAAI;CACzC;CACA;CACA;CACA;CACA;CACD,CAAC;AAEF,MAAa,aAAa;CACxB;CACA;CACA;CACA;CACA;CACD;AAED,MAAa,sBAAsB,IAAI,IAAI;CACzC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;AAEF,MAAa,kBAAkB;CAC7B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD;AAED,MAAa,0BAA0B;AAEvC,MAAa,iCAAiC,IAAI,IAAI;CACpD;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CAC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"}
|