Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Implement SourceCode#markVariableAsUsed() #17086

Merged
merged 9 commits into from Apr 20, 2023
Merged

Conversation

nzakas
Copy link
Member

@nzakas nzakas commented Apr 13, 2023

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:

What changes did you make? (Give an overview)

Implements SourceCode#markVariableAsUsed() and sets context.markVariableAsUsed() to use it.

Refs #16999

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

I'm not sure of how I implemented this method. I started out by passing in an Identifier node because we can use that to get the scope and determine if it's a declared variable. This also seemed like it would be the most developer-friendly.

Based on my feedback from @ljharb, I change it to accept a string and optionally a node. I'd like some more feedback on whether this makes sense.

@nzakas nzakas requested a review from a team as a code owner April 13, 2023 19:21
@eslint-github-bot eslint-github-bot bot added the feature This change adds a new feature to ESLint label Apr 13, 2023
@netlify
Copy link

netlify bot commented Apr 13, 2023

👷 Deploy Preview for docs-eslint processing.

Name Link
🔨 Latest commit 6a24d06
🔍 Latest deploy log https://app.netlify.com/sites/docs-eslint/deploys/6438563535794400086d55e2

@netlify
Copy link

netlify bot commented Apr 13, 2023

Deploy Preview for docs-eslint ready!

Name Link
🔨 Latest commit 12019f8
🔍 Latest deploy log https://app.netlify.com/sites/docs-eslint/deploys/64419aa6d3fa99000723ef7d
😎 Deploy Preview https://deploy-preview-17086--docs-eslint.netlify.app/extend/custom-rules
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site settings.

@ljharb
Copy link
Sponsor Contributor

ljharb commented Apr 13, 2023

We're currently doing context.markVariableAsUsed() in 3 places across 2 rules - jsx-uses-react (which only applies to those not using the new React jsx runtime), and jsx-uses-vars (which continues to apply to jsx). All 3 use cases do indeed pass a string - 1 of them has an AST node available, but the other 2 provide a string only, from eslint settings, so I'm not sure what I'd have to do to make that work.

What's the benefit of this change, though? Whether a variable is used or not seems very context-dependent to me, more than just the static source code can know.

@nzakas
Copy link
Member Author

nzakas commented Apr 13, 2023

This is part of the work for #16999. In order to allow ESLint to lint other languages, we need to remove anything that is JS-specific from context and move it to SourceCode. So context will become a language-neutral access point for ESLint functionality and anything specific to the code being linted will end up SourceCode. Most functionality is already on SourceCode, we just got a bit lazy with defining where these methods go.

What I'm interested in knowing about eslint-plugin-react's usage is whether or not you have an Identifier node related to the variable you're marking as read? I just don't want to implement something that makes it impossible for you to switch to the new API.

@ljharb
Copy link
Sponsor Contributor

ljharb commented Apr 13, 2023

No, for the cases where it's a string from settings (like "React" or "createElement" or something), we have no nodes at all, and this change would presumably force us to add some visitors to locate the nodes.

@nzakas
Copy link
Member Author

nzakas commented Apr 17, 2023

Okay, that's what I needed to know. I'll change the API to be markVariableAsUsed(string, refNode) to better match what we already have.

Comment on lines 693 to 694
const hasSpecialScope = this.scopeManager.isGlobalReturn() ||
this.scopeManager.isModule();
Copy link
Member

Choose a reason for hiding this comment

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

This looks like a breaking change because custom scope managers are not required to provide these methods.

In the parseForESLint interface specification, we require parsers to return a ScopeManager object whose interface doesn't mention isGlobalReturn() and lists isModule() as deprecated and not used in ESLint:

### Deprecated members
Those members are defined but not used in ESLint.
#### isModule()
* **Parameters:**
* **Return type:** `boolean`
* **Description:** `true` if this program is module.

Copy link
Member

Choose a reason for hiding this comment

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

I think the goal here is just, when the Program node is passed, to return the innermost top-level scope instead of the outermost (global) scope that getScope() returns, so if we want to avoid analyzing configured language options, perhaps we could check the scopes directly:

const initialScope = currentScope.type === "global" && currentScope.childScopes.length > 0 && currentScope.childScopes[0].block === this.ast
            ? currentScope.childScopes[0]
            : currentScope;

or maybe do something like this:

const initialScope = refNode === this.ast
            ? this.scopeManager.acquire(refNode, /* inner = */ true)
            : this.getScope(refNode);

Copy link
Member Author

Choose a reason for hiding this comment

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

Ah, that's brilliant. I'll update the logic.

docs/src/extend/custom-rules.md Outdated Show resolved Hide resolved
docs/src/extend/custom-rules.md Outdated Show resolved Hide resolved
@mdjermanovic
Copy link
Member

There's a merge conflict now.

nzakas and others added 8 commits April 20, 2023 11:57
Implements `SourceCode#markVariableAsUsed()` while leaving
`context.markVariableAsUsed()` alone.

Refs #16999
Co-authored-by: Milos Djermanovic <milos.djermanovic@gmail.com>
Co-authored-by: Milos Djermanovic <milos.djermanovic@gmail.com>
Co-authored-by: Milos Djermanovic <milos.djermanovic@gmail.com>
@nzakas
Copy link
Member Author

nzakas commented Apr 20, 2023

Yup, updating the docs now.

@mdjermanovic mdjermanovic added the accepted There is consensus among the team that this change meets the criteria for inclusion label Apr 20, 2023
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!

@mdjermanovic mdjermanovic merged commit 3f7af9f into main Apr 20, 2023
22 checks passed
@mdjermanovic mdjermanovic deleted the mark-variable-used branch April 20, 2023 23:15
crapStone pushed a commit to Calciumdibromid/CaBr2 that referenced this pull request Apr 27, 2023
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [eslint](https://eslint.org) ([source](https://github.com/eslint/eslint)) | devDependencies | minor | [`8.37.0` -> `8.39.0`](https://renovatebot.com/diffs/npm/eslint/8.37.0/8.39.0) |

---

### Release Notes

<details>
<summary>eslint/eslint</summary>

### [`v8.39.0`](https://github.com/eslint/eslint/releases/tag/v8.39.0)

[Compare Source](eslint/eslint@v8.38.0...v8.39.0)

#### Features

-   [`3f7af9f`](eslint/eslint@3f7af9f) feat: Implement `SourceCode#markVariableAsUsed()` ([#&#8203;17086](eslint/eslint#17086)) (Nicholas C. Zakas)

#### Documentation

-   [`6987dc5`](eslint/eslint@6987dc5) docs: Fix formatting in Custom Rules docs ([#&#8203;17097](eslint/eslint#17097)) (Milos Djermanovic)
-   [`4ee92e5`](eslint/eslint@4ee92e5) docs: Update README (GitHub Actions Bot)
-   [`d8e9887`](eslint/eslint@d8e9887) docs: Custom Rules cleanup/expansion ([#&#8203;16906](eslint/eslint#16906)) (Ben Perlmutter)
-   [`1fea279`](eslint/eslint@1fea279) docs: Clarify how to add to tsc agenda ([#&#8203;17084](eslint/eslint#17084)) (Nicholas C. Zakas)
-   [`970ef1c`](eslint/eslint@970ef1c) docs: Update triage board location (Nicholas C. Zakas)
-   [`6d8bffd`](eslint/eslint@6d8bffd) docs: Update README (GitHub Actions Bot)

#### Chores

-   [`60a6f26`](eslint/eslint@60a6f26) chore: upgrade [@&#8203;eslint/js](https://github.com/eslint/js)[@&#8203;8](https://github.com/8).39.0 ([#&#8203;17102](eslint/eslint#17102)) (Milos Djermanovic)
-   [`d5ba5c0`](eslint/eslint@d5ba5c0) chore: package.json update for [@&#8203;eslint/js](https://github.com/eslint/js) release (ESLint Jenkins)
-   [`f57eff2`](eslint/eslint@f57eff2) ci: run tests on Node.js v20 ([#&#8203;17093](eslint/eslint#17093)) (Nitin Kumar)
-   [`9d1b8fc`](eslint/eslint@9d1b8fc) perf: Binary search in token store `utils.search` ([#&#8203;17066](eslint/eslint#17066)) (Francesco Trotta)
-   [`07a4435`](eslint/eslint@07a4435) chore: Add request for minimal repro to bug report ([#&#8203;17081](eslint/eslint#17081)) (Nicholas C. Zakas)
-   [`eac4943`](eslint/eslint@eac4943) refactor: remove unnecessary use of `SourceCode#getAncestors` in rules ([#&#8203;17075](eslint/eslint#17075)) (Milos Djermanovic)
-   [`0a7b60a`](eslint/eslint@0a7b60a) chore: update description of `SourceCode#getDeclaredVariables` ([#&#8203;17072](eslint/eslint#17072)) (Milos Djermanovic)
-   [`6e2df71`](eslint/eslint@6e2df71) chore: remove unnecessary references to the LICENSE file ([#&#8203;17071](eslint/eslint#17071)) (Milos Djermanovic)

### [`v8.38.0`](https://github.com/eslint/eslint/releases/tag/v8.38.0)

[Compare Source](eslint/eslint@v8.37.0...v8.38.0)

#### Features

-   [`a1d561d`](eslint/eslint@a1d561d) feat: Move getDeclaredVariables and getAncestors to SourceCode ([#&#8203;17059](eslint/eslint#17059)) (Nicholas C. Zakas)

#### Bug Fixes

-   [`1c1ece2`](eslint/eslint@1c1ece2) fix: do not report on `RegExp(...args)` in `require-unicode-regexp` ([#&#8203;17037](eslint/eslint#17037)) (Francesco Trotta)

#### Documentation

-   [`7162d34`](eslint/eslint@7162d34) docs: Mention new config system is complete ([#&#8203;17068](eslint/eslint#17068)) (Nicholas C. Zakas)
-   [`0fd6bb2`](eslint/eslint@0fd6bb2) docs: Update README (GitHub Actions Bot)
-   [`c83531c`](eslint/eslint@c83531c) docs: Update/remove external links, eg. point to `eslint-community` ([#&#8203;17061](eslint/eslint#17061)) (Pelle Wessman)
-   [`a3aa6f5`](eslint/eslint@a3aa6f5) docs: Clarify `no-div-regex` rule docs ([#&#8203;17051](eslint/eslint#17051)) (Francesco Trotta)
-   [`b0f11cf`](eslint/eslint@b0f11cf) docs: Update README (GitHub Actions Bot)
-   [`da8d52a`](eslint/eslint@da8d52a) docs: Update the second object instance for the "no-new" rule ([#&#8203;17020](eslint/eslint#17020)) (Ahmadou Waly NDIAYE)
-   [`518130a`](eslint/eslint@518130a) docs: switch language based on current path ([#&#8203;16687](eslint/eslint#16687)) (Percy Ma)
-   [`24206c4`](eslint/eslint@24206c4) docs: Update README (GitHub Actions Bot)

#### Chores

-   [`59ed060`](eslint/eslint@59ed060) chore: upgrade [@&#8203;eslint/js](https://github.com/eslint/js)[@&#8203;8](https://github.com/8).38.0 ([#&#8203;17069](eslint/eslint#17069)) (Milos Djermanovic)
-   [`88c0898`](eslint/eslint@88c0898) chore: package.json update for [@&#8203;eslint/js](https://github.com/eslint/js) release (ESLint Jenkins)
-   [`cf682d2`](eslint/eslint@cf682d2) refactor: simplify new-parens rule schema ([#&#8203;17060](eslint/eslint#17060)) (MHO)
-   [`0dde022`](eslint/eslint@0dde022) ci: bump actions/add-to-project from 0.4.1 to 0.5.0 ([#&#8203;17055](eslint/eslint#17055)) (dependabot\[bot])

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNS4zNS4xIiwidXBkYXRlZEluVmVyIjoiMzUuNTUuMSJ9-->

Co-authored-by: cabr2-bot <cabr2.help@gmail.com>
Reviewed-on: https://codeberg.org/Calciumdibromid/CaBr2/pulls/1852
Reviewed-by: Epsilon_02 <epsilon_02@noreply.codeberg.org>
Co-authored-by: Calciumdibromid Bot <cabr2_bot@noreply.codeberg.org>
Co-committed-by: Calciumdibromid Bot <cabr2_bot@noreply.codeberg.org>
@eslint-github-bot eslint-github-bot bot locked and limited conversation to collaborators Oct 18, 2023
@eslint-github-bot eslint-github-bot bot added the archived due to age This issue has been archived; please open a new issue for any further discussion label Oct 18, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
accepted There is consensus among the team that this change meets the criteria for inclusion archived due to age This issue has been archived; please open a new issue for any further discussion feature This change adds a new feature to ESLint
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants