Skip to content

feat: add jsx-no-conflicting-pragmas rule - #1505

Open
bartlomieju wants to merge 2 commits into
mainfrom
feat-jsx-no-conflicting-pragmas
Open

feat: add jsx-no-conflicting-pragmas rule#1505
bartlomieju wants to merge 2 commits into
mainfrom
feat-jsx-no-conflicting-pragmas

Conversation

@bartlomieju

Copy link
Copy Markdown
Member

Adds a rule that flags mixing the automatic-runtime pragma
@jsxImportSource with the classic-runtime pragmas @jsx /
@jsxFragment (or @jsxFrag) in the same file:

/** @jsxImportSource https://esm.sh/preact */
/** @jsx h */
/** @jsxFragment Fragment */

When @jsxImportSource is set the file uses the automatic runtime, so the
@jsx and @jsxFragment pragmas are silently ignored. Having both is a
footgun — you should use one runtime or the other. The rule reports each
classic pragma when an @jsxImportSource pragma is also present, and only
looks at the file's leading comments, where pragmas actually take effect.

The rule is tagged react/jsx but intentionally left out of
recommended, so it must be enabled explicitly. Happy to promote it to
recommended if preferred — flagging the decision rather than making it.

Closes #969.

Flags using the automatic-runtime pragma `@jsxImportSource` together with
the classic-runtime pragmas `@jsx` / `@jsxFragment`. When both are
present the classic pragmas are silently ignored, which is a footgun.

The rule is tagged `react`/`jsx` but not `recommended`, so it must be
enabled explicitly for now.

Closes #969.
@bartlomieju

Copy link
Copy Markdown
Member Author

Verdict: LGTM — correct and well-tested. Recommend merge after resolving the schema conflict + rebase (new rule → maintainer product decision, which you've explicitly flagged). Not auto-merging (new rule).

Correctness — verified the regex boundaries (the crux of this rule)
I simulated both patterns against the tricky inputs; all behave exactly as documented:

  • @jsxImportSource\b matches @jsxImportSource but not @jsxImportSourceTypes (the T after Source blocks the \b) — so a types-only directive doesn't switch the runtime. ✓
  • @jsx(Frag(ment)?)?\b matches @jsx, @jsxFrag, @jsxFragment, but not @jsxImportSource, @jsxRuntime, or @jsxFragmentFoo (word-boundary correctly rejects longer identifiers). ✓
  • Logic is order-independent and only inspects comments before the first statement (where pragmas actually take effect); comment-only files fall back to scanning all comments. All of this is covered by the valid/invalid tests, including the multi-pragma and reversed-order cases.

Perf: fine — two Lazy-compiled regex is_match calls per leading comment; leading comments are few.

Minor

  • A single comment holding both @jsxImportSource and a classic pragma gets flagged as a whole (range = full comment). Reasonable; just noting the range granularity.
  • No docs/rules/jsx_no_conflicting_pragmas.md / docs() in the diff — new rules conventionally ship docs, and the docs.json CI diff expects them.

Housekeeping / blockers

No code changes requested. Solid rule; just docs + the schema-file conflict + rebase before landing.

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.

Lint proper use of jsx pragma

1 participant