Skip to content

MIL-1559: no-giant-component flags non-React TypeScript modules - #525

Merged
aidenybai merged 6 commits into
mainfrom
ray/e1d4d495
May 28, 2026
Merged

MIL-1559: no-giant-component flags non-React TypeScript modules#525
aidenybai merged 6 commits into
mainfrom
ray/e1d4d495

Conversation

@rayhanadev

@rayhanadev rayhanadev commented May 27, 2026

Copy link
Copy Markdown
Member

Why?

Catches false positives where react-doctor/no-giant-component treated large PascalCase helpers as React components even when they did not render React output.

The rule previously used a name-and-size heuristic: any oversized PascalCase function declaration or PascalCase function assignment could be reported as a component. That was too broad for service modules, adapters, and data helpers that happen to use PascalCase naming. The rule should only warn when the oversized candidate is actually component-shaped, so this change requires direct React render evidence before reporting.

RDE validation was run against the first 1000 distinct repos from repos.json, expanding to 4350 rootDir scans. Both baseline and this branch produced 0 react-doctor/no-giant-component diagnostics, parity diff was [], and no false positives were found.

What changed?

  • Tightened react-doctor/no-giant-component so oversized PascalCase function candidates must contain direct React render output before they are reported.
  • Added render-output detection for JSX, JSX fragments, import { createElement } from "react", and React default/namespace imports used as React.createElement(...).
  • Made createElement evidence scope-aware so shadowed imports, non-React imports, local helpers, and global React.createElement without an import do not count.
  • Pruned nested functions/classes while scanning for render evidence, so JSX inside an inner callback/component does not classify the outer function as a component.
  • Added focused adversarial tests for real component cases and non-component false-positive traps.
  • Updated the rule test harness to attach source locations from parser offsets, allowing line-count rules to be unit tested directly.
  • Added a patch changeset for oxlint-plugin-react-doctor.

Before:

function ExampleService() {
  // 300+ lines of fetch/data helper logic
  return fetch("/api/example");
}

This could be reported as:

Component "ExampleService" is 302 lines — consider breaking it into smaller focused components

After:

function ExampleService() {
  // 300+ lines of fetch/data helper logic
  return fetch("/api/example");
}

This stays quiet because it has no direct React render output.

A real oversized component is still reported:

function GiantComponent() {
  // 300+ lines of component logic
  return <main />;
}

Test plan

Users can verify correctness with:

pnpm exec vp test run packages/oxlint-plugin-react-doctor/src/plugin/rules/architecture/no-giant-component.test.ts
pnpm exec vp test run packages/react-doctor/tests/run-oxlint/architecture.test.ts
pnpm --filter oxlint-plugin-react-doctor typecheck
pnpm exec vp fmt --check .changeset/quiet-giant-components.md packages/oxlint-plugin-react-doctor/src/plugin/rules/architecture/no-giant-component.test.ts packages/oxlint-plugin-react-doctor/src/plugin/rules/architecture/no-giant-component.ts packages/oxlint-plugin-react-doctor/src/plugin/utils/function-contains-react-render-output.ts packages/oxlint-plugin-react-doctor/src/test-utils/run-rule.ts packages/oxlint-plugin-react-doctor/src/test-utils/attach-source-locations.ts

Note

Low Risk
Narrows an architecture lint heuristic and adds tests; no auth, data, or runtime product behavior changes.

Overview
no-giant-component no longer warns on every oversized PascalCase function. It now requires direct React render evidence (JSX/fragments or scope-resolved createElement from react / React.createElement) before reporting, so large service-style helpers stay quiet.

Detection is scope-aware: nested inner components don’t count as outer render output; shadowed or non-React createElement, locals, and unimported global React are ignored. The rule test harness synthesizes loc from parser offsets so line-threshold behavior is covered in unit tests, with adversarial pass/fail fixtures.

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

Co-authored-by: Cursor <cursoragent@cursor.com>
@rayhanadev
rayhanadev marked this pull request as ready for review May 27, 2026 19:11
Copilot AI review requested due to automatic review settings May 27, 2026 19:11
Co-authored-by: Cursor <cursoragent@cursor.com>
@rayhanadev

Copy link
Copy Markdown
Member Author

bugbot run

Co-authored-by: Cursor <cursoragent@cursor.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@rayhanadev rayhanadev changed the title Tighten giant component detection MIL-1559: no-giant-component flags non-React TypeScript modules May 27, 2026
cursor[bot]

This comment was marked as resolved.

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 4 additional findings.

Open in Devin Review

Co-authored-by: Cursor <cursoragent@cursor.com>
devin-ai-integration[bot]

This comment was marked as resolved.

@aidenybai
aidenybai merged commit 928f21c into main May 28, 2026
15 checks passed
@aidenybai
aidenybai deleted the ray/e1d4d495 branch May 28, 2026 00:34
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.

no-giant-component fires on non-React .ts files (service/adapter object literals)

3 participants