Skip to content

Conversation

@Pixel998
Copy link
Contributor

Prerequisites checklist

What is the purpose of this pull request? (put an "X" next to an item)

[ ] Documentation update
[ ] Bug fix (template)
[ ] New rule (template)
[ ] Changes an existing rule (template)
[ ] Add autofix to a rule
[ ] Add a CLI option
[x] Add something to the core
[ ] Other, please explain:

This PR enables JSX reference tracking in ESLint by passing the jsx option to eslint-scope. This feature was already implemented in eslint-scope but wasn't being utilized in ESLint.

What changes did you make? (Give an overview)

  • Modified lib/languages/js/index.js and lib/linter/linter.js to pass jsx: ecmaFeatures.jsx to the scope analyzer
  • Added tests for no-undef rule to verify JSX element references are properly tracked
  • Added tests for no-use-before-define rule to verify JSX usage follows definition order rules

Fixes #19495

Is there anything you'd like reviewers to focus on?

@github-project-automation github-project-automation bot moved this to Needs Triage in Triage Sep 23, 2025
@eslint-github-bot eslint-github-bot bot added breaking This change is backwards-incompatible feature This change adds a new feature to ESLint labels Sep 23, 2025
@netlify
Copy link

netlify bot commented Sep 23, 2025

Deploy Preview for docs-eslint canceled.

Name Link
🔨 Latest commit 2a1eb58
🔍 Latest deploy log https://app.netlify.com/projects/docs-eslint/deploys/69305252a0b480000822d6df

@github-actions github-actions bot added the core Relates to ESLint's core APIs and features label Sep 23, 2025
Copy link
Contributor

@JoshuaKGoldberg JoshuaKGoldberg left a comment

Choose a reason for hiding this comment

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

🚀 LGTM, thanks! I couldn't find any other uses that need to be updated. But I'm not a deep expert here and should defer to a second review.

@github-actions
Copy link

github-actions bot commented Oct 5, 2025

Hi everyone, it looks like we lost track of this pull request. Please review and see what the next steps are. This pull request will auto-close in 7 days without an update.

@github-actions github-actions bot added the Stale label Oct 5, 2025
@fasttime fasttime removed the Stale label Oct 6, 2025
@mdjermanovic mdjermanovic added the accepted There is consensus among the team that this change meets the criteria for inclusion label Oct 6, 2025
@fasttime fasttime moved this from Needs Triage to Blocked in Triage Oct 6, 2025
aladdin-add
aladdin-add previously approved these changes Oct 24, 2025
Copy link
Member

@aladdin-add aladdin-add left a comment

Choose a reason for hiding this comment

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

LGTM, thanks!

@mdjermanovic
Copy link
Member

I think we should update docs here, as Reference#identifier can now also be a JSXIdentifier node:

#### identifier
- **Type:** `ASTNode`
- **Description:** The `Identifier` node of this reference.

And types:

eslint/lib/types/index.d.ts

Lines 179 to 180 in a463e7b

interface Reference {
identifier: ESTree.Identifier;

@mdjermanovic
Copy link
Member

I think we could also update the no-useless-assignment rule to include variables that have JSXIdentifier in checking:

if (
targetAssignment.variable.references.some(
ref => ref.identifier.type !== "Identifier",
)
) {
/**
* Skip checking for a variable that has at least one non-identifier reference.
* It's generated by plugins and cannot be handled reliably in the core rule.
*/
return;
}

Identifier(node) {

@Pixel998 Pixel998 dismissed stale reviews from aladdin-add and JoshuaKGoldberg via d441611 November 25, 2025 13:20
@github-actions github-actions bot added the rule Relates to ESLint's core rules label Nov 25, 2025
@Pixel998
Copy link
Contributor Author

I’ve updated the scope manager documentation, the no-useless-assignment rule, and the migration guide. For the type update, we can either define JSXIdentifier inline:

interface JSXIdentifier extends ESTree.BaseNode {
    type: "JSXIdentifier";
    name: string;
}

or use an existing type package such as @types/estree-jsx. What do you think?

@mdjermanovic
Copy link
Member

I’ve updated the scope manager documentation, the no-useless-assignment rule, and the migration guide. For the type update, we can either define JSXIdentifier inline:

interface JSXIdentifier extends ESTree.BaseNode {
    type: "JSXIdentifier";
    name: string;
}

or use an existing type package such as @types/estree-jsx. What do you think?

I think an inline definition would be fine, but would like @fasttime's opinion as this should probably be aligned with eslint/js#709 (and we'll eventually just re-export types from eslint-scope here?).

@fasttime
Copy link
Member

I think an inline definition would be fine, but would like @fasttime's opinion as this should probably be aligned with eslint/js#709 (and we'll eventually just re-export types from eslint-scope here?).

I also think an inline definition should be fine. ESLint doesn’t import types from eslint-scope, in fact, the opposite is true for historical reasons. But since the JSXIdentifier type definition is small, we could define it in both ESLint and eslint-scope for now, and later consider moving it to a more appropriate location (for example the Espree types).

@Pixel998 Pixel998 marked this pull request as ready for review November 26, 2025 13:09
@Pixel998 Pixel998 requested a review from a team as a code owner November 26, 2025 13:09
@Pixel998
Copy link
Contributor Author

I’ve updated the type accordingly. This should now be ready for review.

@mdjermanovic mdjermanovic moved this from Blocked to Implementing in Triage Nov 26, 2025
@DMartens
Copy link
Contributor

DMartens commented Dec 1, 2025

Changes overall LGTM, thanks.
Maybe we should also add some basic tests for the rule no-unused-vars.

Copy link
Member

@mdjermanovic mdjermanovic left a comment

Choose a reason for hiding this comment

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

LGTM, thanks! Leaving open for @nzakas to verify.

@mdjermanovic mdjermanovic moved this from Implementing to Second Review Needed in Triage Dec 4, 2025
Copy link
Contributor

@snitin315 snitin315 left a comment

Choose a reason for hiding this comment

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

LGTM, thanks! Left an optional suggestion.

}
```

Prior to v10.0.0, ESLint did not recognize that `<Card>` is a reference to the imported `Card`, which could result in false positives such as reporting `Card` as "defined but never used" ([`no-unused-vars`](../rules/no-unused-vars)) or false negatives such as failing to report `Card` as undefined ([`no-undef`](../rules/no-undef)) if the import is removed. Starting with v10.0.0, `<Card>` is treated as a normal reference to the variable in scope. This brings JSX handling in line with developer expectations and improves the linting experience for modern JavaScript applications using JSX.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
Prior to v10.0.0, ESLint did not recognize that `<Card>` is a reference to the imported `Card`, which could result in false positives such as reporting `Card` as "defined but never used" ([`no-unused-vars`](../rules/no-unused-vars)) or false negatives such as failing to report `Card` as undefined ([`no-undef`](../rules/no-undef)) if the import is removed. Starting with v10.0.0, `<Card>` is treated as a normal reference to the variable in scope. This brings JSX handling in line with developer expectations and improves the linting experience for modern JavaScript applications using JSX.
Prior to v10.0.0, ESLint did not recognize that `<Card>` is a reference to the imported `Card`, which could result in false positives such as reporting `Card` as "defined but never used" ([`no-unused-vars`](../rules/no-unused-vars)) or false negatives such as failing to report `Card` as undefined ([`no-undef`](../rules/no-undef)) if the import is removed. Starting with v10.0.0, `<Card>` is treated as a normal reference to the variable in scope. This brings JSX handling in line with developer expectations and enhances the linting experience for modern JavaScript applications that use JSX.

Copy link
Member

@nzakas nzakas left a comment

Choose a reason for hiding this comment

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

LGTM. Thanks!

@nzakas nzakas merged commit c7046e6 into eslint:main Dec 8, 2025
32 checks passed
@github-project-automation github-project-automation bot moved this from Second Review Needed to Complete in Triage Dec 8, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

accepted There is consensus among the team that this change meets the criteria for inclusion breaking This change is backwards-incompatible core Relates to ESLint's core APIs and features feature This change adds a new feature to ESLint rule Relates to ESLint's core rules

Projects

Status: Complete

Development

Successfully merging this pull request may close these issues.

Change Request: Enable JSX reference tracking

8 participants