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: Add reportUsedIgnorePattern option to no-unused-vars rule #17662

Merged
merged 8 commits into from Apr 2, 2024

Conversation

Pearce-Ropion
Copy link
Contributor

@Pearce-Ropion Pearce-Ropion commented Oct 18, 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
  • Add something to the core
  • Other, please explain:

What rule do you want to change?

no-unused-vars

What change do you want to make (place an "X" next to just one item)?

  • Generate more warnings
  • Generate fewer warnings
  • Implement autofix
  • Implement suggestions

How will the change be implemented (place an "X" next to just one item)?

  • A new option
  • A new default behavior
  • Other

Please provide some example code that this change will affect:

Example 1:

/* eslint no-unused-vars: ["error", { "varsIgnorePattern": "^_" }] */

const _a = 5;
const _b = _a + 5

Example 2:

/* eslint no-unused-vars: ["error", { "argsIgnorePattern": "^_" }] */

function foo(_a) {
  return _a + 5
}

Example 3:

/* eslint no-unused-vars: ["error", { "destructuredArrayIgnorePattern": "^_" }] */

const [ a, _b ] = items;
console.log(a + _b);

Example 4:

/* eslint no-unused-vars: ["error", { "caughtErrorsIgnorePattern": "^_" }] */

try {}
catch(_err) {
  console.error(_err);
}

What does the rule currently do for this code?

In all examples, no warnings are reported.

What will the rule do after it's changed?

When the new option reportUsedIgnorePattern is enabled, each of the examples above will report; indicating that a variable that has been marked as an ignored unused variable is being used.

What changes did you make? (Give an overview)

This change adds a new option reportUsedIgnorePattern to the no-unused-vars rule. When enabled, the rule will report any instances of variables that match any of the valid ignore pattern options when that variable is actually being used.

Resolves: #17568

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

When finding all references in order to report on the correct nodes, it is also finding the variable declaration. So a question for the team would be which nodes should this option report on:

  • Should all references including the declaration be reported?
  • Should only the variable declaration be reported?
  • Should only references not including the declaration be reported

@Pearce-Ropion Pearce-Ropion requested a review from a team as a code owner October 18, 2023 18:17
@linux-foundation-easycla
Copy link

linux-foundation-easycla bot commented Oct 18, 2023

CLA Signed

The committers listed above are authorized under a signed CLA.

@eslint-github-bot
Copy link

Hi @Pearce-Ropion!, thanks for the Pull Request

The pull request title isn't properly formatted. We ask that you update the pull request title to match this format, as we use it to generate changelogs and automate releases.

  • The commit message tag wasn't recognized. Did you mean "docs", "fix", or "feat"?
  • There should be a space following the initial tag and colon, for example 'feat: Message'.
  • The first letter of the tag should be in lowercase

To Fix: You can fix this problem by clicking 'Edit' next to the pull request title at the top of this page.

Read more about contributing to ESLint here

@netlify
Copy link

netlify bot commented Oct 18, 2023

Deploy Preview for docs-eslint canceled.

Name Link
🔨 Latest commit 9fa1956
🔍 Latest deploy log https://app.netlify.com/sites/docs-eslint/deploys/660398e1192bd30008c67bd6

@Pearce-Ropion Pearce-Ropion changed the title Add reportUsedIgnorePattern option to no-unused-vars rule feat: Add reportUsedIgnorePattern option to no-unused-vars rule Oct 18, 2023
@eslint-github-bot eslint-github-bot bot added the feature This change adds a new feature to ESLint label Oct 18, 2023
@mdjermanovic
Copy link
Member

  • Should all references including the declaration be reported?
  • Should only the variable declaration be reported?
  • Should only references not including the declaration be reported

Would it make sense to report only on the reasons the variable is considered used, which are usually its read references?

This is how it currently works:

/* eslint no-unused-vars: ["error", {
    varsIgnorePattern: "^_",
    reportUsedIgnorePattern: true
}] */

var _a; // not reported

_a = 1; // this is reported but doesn't seem relevant?

foo(_a); // this is also reported, ok

But this variable is considered used only because of the read reference so it might make sense to report like this:

/* eslint no-unused-vars: ["error", {
    varsIgnorePattern: "^_",
    reportUsedIgnorePattern: true
}] */

var _a; // not reported

_a = 1; // not reported

foo(_a); // reported

@Pearce-Ropion
Copy link
Contributor Author

Pearce-Ropion commented Oct 20, 2023

  • Should all references including the declaration be reported?
  • Should only the variable declaration be reported?
  • Should only references not including the declaration be reported

Would it make sense to report only on the reasons the variable is considered used, which are usually its read references?

This is how it currently works:

/* eslint no-unused-vars: ["error", {
    varsIgnorePattern: "^_",
    reportUsedIgnorePattern: true
}] */

var _a; // not reported

_a = 1; // this is reported but doesn't seem relevant?

foo(_a); // this is also reported, ok

But this variable is considered used only because of the read reference so it might make sense to report like this:

/* eslint no-unused-vars: ["error", {
    varsIgnorePattern: "^_",
    reportUsedIgnorePattern: true
}] */

var _a; // not reported

_a = 1; // not reported

foo(_a); // reported

That makes sense to me. I couldn't entirely remember what counted as used. However, I would also expect that a user shouldn't be allowed to write to an ignored unused variable since it should be unused.

@Tanujkanti4441 Tanujkanti4441 added the rule Relates to ESLint's core rules label Oct 23, 2023
lib/rules/no-unused-vars.js Outdated Show resolved Hide resolved
Copy link

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.

@Pearce-Ropion
Copy link
Contributor Author

I changed it to skip all variable initializations but otherwise report on all references. I also doesn't check whether the variable scope matches anymore so it can handle variables defined in the outer scope which are used in an inner scope.

@Pearce-Ropion
Copy link
Contributor Author

@mdjermanovic I think this is working as expected now. Can you think of any other cases that I could test for? Otherwise, I think we are good to go.

Copy link

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 Dec 10, 2023
@Tanujkanti4441 Tanujkanti4441 requested review from nzakas and snitin315 and removed request for costinsin December 11, 2023 02:46
@mdjermanovic mdjermanovic added accepted There is consensus among the team that this change meets the criteria for inclusion enhancement This change enhances an existing feature of ESLint labels Dec 15, 2023
@mdjermanovic
Copy link
Member

@Pearce-Ropion apologies for the delay in reviewing this PR.

I changed it to skip all variable initializations but otherwise report on all references.

I'm not sure what the common use cases for the varsIgnorePattern option are, but if user has a code like the following where the rule doesn't report any errors:

/*eslint no-unused-vars: ["error", { varsIgnorePattern: "^_", reportUsedIgnorePattern: true }]*/

var _foo;

_foo = 5;

and then they add more code that causes the variable to be considered used, so that the rule now reports it:

/*eslint no-unused-vars: ["error", { varsIgnorePattern: "^_", reportUsedIgnorePattern: true }]*/

var _foo;

_foo = 5;

bar(_foo);

then, I think it makes the most sense to report only on the references where this rule considers the variable to be used: _foo in bar(_foo), because _foo = 5 has no effect on whether the variable is considered used, and it was valid before bar(_foo) was added.

Alternatively, we could report only the declaration assuming that the variable name is wrong because it was intended to be used (as opposed to reporting references, in which case the assumption is that the variable that wasn't intended to be used is mistakenly used).

Curious what others think about this.

@mdjermanovic
Copy link
Member

In this case, the message seems misleading:

/*eslint no-unused-vars: ["error", {
    "reportUsedIgnorePattern": true,
    "destructuredArrayIgnorePattern": "^_",
    "varsIgnorePattern": "[iI]gnored"
}]*/

let _x; // '_x' is marked as ignored but is used. Used vars must not match /[iI]gnored/u.

[_x] = arr;

foo(_x);

@Tanujkanti4441
Copy link
Contributor

Hi @Pearce-Ropion, some changes are requested. you can check out.

@@ -92,7 +103,8 @@ module.exports = {
vars: "all",
args: "after-used",
ignoreRestSiblings: false,
caughtErrors: "all"
caughtErrors: "all",
reportUsedIgnorePattern: false,
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
reportUsedIgnorePattern: false,
reportUsedIgnorePattern: false

To fix the lint error.

@mdjermanovic
Copy link
Member

In this case, the message seems misleading:

/*eslint no-unused-vars: ["error", {
    "reportUsedIgnorePattern": true,
    "destructuredArrayIgnorePattern": "^_",
    "varsIgnorePattern": "[iI]gnored"
}]*/

let _x; // '_x' is marked as ignored but is used. Used vars must not match /[iI]gnored/u.

[_x] = arr;

foo(_x);

I'm still getting the same error, looks like this case still hasn't been addressed?

@mdjermanovic
Copy link
Member

Here's a similar case that should also be fixed:

/*eslint no-unused-vars: ["error", {
    "reportUsedIgnorePattern": true,
    "destructuredArrayIgnorePattern": "^_",
    "varsIgnorePattern": "[iI]gnored"
}]*/

const [ignored] = arr; // 'ignored' is marked as ignored but is used. Used elements of array destructuring must not match /^_/u.

foo(ignored);

The message should be: 'ignored' is marked as ignored but is used. Used vars must not match /[iI]gnored/u.

Comment on lines 720 to 729
if (config.reportUsedIgnorePattern && isUsedVariable(variable)) {
usedIgnoredVars.push(variable);
}
Copy link
Member

Choose a reason for hiding this comment

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

Instead of collecting these vars and later figuring out why they were considered as used ignored, we could just report them right away with the data we have at this point:

Suggested change
if (config.reportUsedIgnorePattern && isUsedVariable(variable)) {
usedIgnoredVars.push(variable);
}
if (config.reportUsedIgnorePattern && isUsedVariable(variable)) {
context.report({
node: def.name,
messageId: "usedIgnoredVar",
data: {
varName: variable.name,
additional: `. Used elements of array destructuring must not match ${config.destructuredArrayIgnorePattern}`
}
});
}

(the same for catch arguments, params and variables).

That would fix #17662 (comment) and #17662 (comment).

@nzakas
Copy link
Member

nzakas commented Mar 22, 2024

@Pearce-Ropion are you still working on this?

@Pearce-Ropion
Copy link
Contributor Author

@Pearce-Ropion are you still working on this?

Yes, apologies. I've been slammed with work. I'll get the proposed suggestions in this weekend

Pearce-Ropion and others added 2 commits March 26, 2024 19:34
Address comments

Fix tests

Report on all variables except for initializers

Report only on declarations

Match message formatting with other rule messages

Move variable.eslintUsed into isUsedVariable function

Refactor report messages for consistency

Fix tests
@Pearce-Ropion
Copy link
Contributor Author

Ok, I've applied @mdjermanovic's suggestions to report as soon as we detect the used ignored variable. I also explicitly added the test cases that @mdjermanovic used.

I've also updated the message data handling. I had already updated the other message data handlers as per previous comments, but I noticed that all 3 of the message data getters were doing basically the same thing. So I've added a getVariableDescription helper function to get the required info for the message data base on the type of the variable that is currently being reported.

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. Would like @mdjermanovic to review before merging.

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 for contributing!

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 contributor pool enhancement This change enhances an existing feature of ESLint feature This change adds a new feature to ESLint rule Relates to ESLint's core rules
Projects
Status: Complete
6 participants