Skip to content

feat: port PR 217 lint rule coverage#251

Open
aidenybai wants to merge 2 commits into
mainfrom
port/pr-217-rule-coverage-clean
Open

feat: port PR 217 lint rule coverage#251
aidenybai wants to merge 2 commits into
mainfrom
port/pr-217-rule-coverage-clean

Conversation

@aidenybai
Copy link
Copy Markdown
Member

@aidenybai aidenybai commented May 15, 2026

Summary

  • Ports the remaining PR improve v2 rasmus #217 false-positive fixes into the current oxlint plugin rules.
  • Adds the missing shadcn/radix, testing/storybook, SWR, React Hook Form, i18n, React Three Fiber, TanStack AI, client, and server/async rule coverage.
  • Regenerates rule registry metadata for the new rule buckets and shared AST helpers.

Test plan

  • nr typecheck
  • nr lint
  • nr test
  • nr format

Note

Medium Risk
Adds many new lint rules and broadens file-pattern heuristics, which can change diagnostics significantly and may introduce false positives/negatives. Also modifies the security-critical nextjs-no-side-effect-in-get-handler detection logic, so rule behavior should be validated against real Next.js route patterns.

Overview
Expands oxlint-plugin-react-doctor with new rule buckets and rules covering i18n, React Hook Form, React Three Fiber, SWR, Storybook/Testing Library, TanStack AI, client event listeners, and server streaming/caching/perf patterns; the rule registry generator and generated rule-registry.ts are updated accordingly.

Improves several existing detectors and constants: broader test/infra path matching, new Next.js route patterns (App Router/OG/cron), additional React unsubscription naming, new thresholds, and refinements to performance/correctness rules (e.g. js-length-check-first, js-set-map-lookups, async-parallel, no-uncontrolled-input, rn-no-raw-text, no-prevent-default).

Hardens nextjs-no-side-effect-in-get-handler by resolving GET handler bodies through simple top-level binding lookup and chained .get(...) handler patterns (and skipping cron routes) before scanning for side effects.

Reviewed by Cursor Bugbot for commit 1e24096. Bugbot is set up for automated code reviews on this repo. Configure here.

Bring over the remaining false-positive fixes and missing oxlint rule families from the v2 PR so the current split-package plugin keeps parity with the intended rule surface.
@vercel
Copy link
Copy Markdown

vercel Bot commented May 15, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
react-doctor-website Ready Ready Preview, Comment May 15, 2026 1:51pm

@reactreview
Copy link
Copy Markdown

reactreview Bot commented May 15, 2026

🔴 React Review0/100 (unchanged) · 0 ❌ errors · 1 ⚠️ warning

Copy prompt for agent
Check if these React Review issues are valid. If so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.

Run this before and after your changes to verify the result:
npx react-doctor@latest --verbose --diff

Do not modify the react-doctor configuration unless explicitly asked.
Fix the underlying code issues instead of changing or suppressing the rules.

React Review found 0 errors and 1 warning. This PR leaves the React health score unchanged.

<file name="packages/oxlint-plugin-react-doctor/src/plugin/rules/client/client-event-listeners.ts">

<violation number="1" location="packages/oxlint-plugin-react-doctor/src/plugin/rules/client/client-event-listeners.ts:23">
Severity: Warning

current.id.name is read 3 times inside this loop — hoist into a const at the top of the loop body

Hoist the deep member access into a const at the top of the loop body: `const { x, y } = obj.deeply.nested`

Rule: `js-cache-property-access`
</violation>

</file>

Reviewed by react-review for commit 7be0058. Configure here.

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 1e24096. Configure here.

if (!isStoryFile) return;
const keyName = isNodeOfType(node.key, "Identifier") ? node.key.name : null;
if (keyName === "play" && playFunctionDepth > 0) playFunctionDepth--;
},
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Storybook rule exit handler missing function-value guard

Medium Severity

The Property enter handler only increments playFunctionDepth when the play property's value is an ArrowFunctionExpression or FunctionExpression. The Property:exit handler decrements for any play property regardless of value type. A nested play property with a non-function value (e.g. play: composedPlay) inside a real play function would decrement the counter prematurely, causing the rule to miss unawaited userEvent calls in the remainder of the outer play function.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 1e24096. Configure here.

import type { EsTreeNode } from "../../utils/es-tree-node.js";

const I18N_IMPORT_SOURCES = new Set(["i18next", "next-intl", "react-i18next"]);
const TRANSLATION_FUNCTION_NAMES = new Set(["t", "i18n.t"]);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unreachable "i18n.t" entry in translation function set

Medium Severity

TRANSLATION_FUNCTION_NAMES includes "i18n.t", but the CallExpression handler only matches Identifier callees via isNodeOfType(node.callee, "Identifier"). An i18n.t() call has a MemberExpression callee, so this entry can never match. Calls like i18n.t(dynamicKey) are silently ignored despite being an intended detection target.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 1e24096. Configure here.

export const testingAwaitUserEvent = defineRule<Rule>({
id: "testing-await-user-event",
severity: "error",
recommendation:
Copy link
Copy Markdown

@vercel vercel Bot May 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The testing-await-user-event rule lacks a test file pattern check, causing it to apply to all files instead of just test files like its sibling rule does.

Fix on Vercel

Comment on lines +50 to +55
if (
!isNodeOfType(node.callee, "Identifier") ||
!translationFunctionNames.has(node.callee.name)
) {
return;
}
Copy link
Copy Markdown

@vercel vercel Bot May 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "i18n.t" entry in TRANSLATION_FUNCTION_NAMES is unreachable dead code because the CallExpression handler only checks for Identifier callees, but i18n.t() calls have a MemberExpression callee.

Fix on Vercel

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants