no-unused-vars reports warning at incorrect position for recursive functions
See original GitHub issueenvironment
Node version: v14.4.0 npm version: v6.14.5 Local ESLint version: v7.12.1 (Currently used) Global ESLint version: v7.8.1
parser
default
Configuration
{
"env": {
"es6": true,
},
"root": true,
"rules": {
"no-unused-vars": ["warn", {"args": "none"}],
},
}
Code being linted:
function fact(num) {
return num * fact(num - 1);
}
command used to lint the code
npx run eslint test.js
What did you expect to happen?
no-unused-var is triggered on the function declaration:
1:10 warning 'fact' is defined but never used no-unused-vars
✖ 1 problem (0 errors, 1 warning)
What actually happened? Please include the actual, raw output from ESLint.
no-unused-var is triggered on the last internal self-reference of the function:
2:15 warning 'fact' is defined but never used no-unused-vars
✖ 1 problem (0 errors, 1 warning)
Are you willing to submit a pull request to fix this bug?
I have never touched eslint’s code but if someone would like to point me in the right direction I’m willing to submit a PR for this.
I would also like to note that this is a regression as eslint 7.1 correctly reports the warning at 1:10, it starts reporting the warning at 2:15 in version 7.2
Issue Analytics
- State:
- Created 3 years ago
- Comments:10 (6 by maintainers)
Top GitHub Comments
Demo link for anyone else who wants to try this.
Thanks for the tip on the v7.1-v7.2 regression - that made it easy to track down. In https://github.com/eslint/eslint/pull/13354 and https://github.com/eslint/eslint/issues/13181, we intentionally changed
no-unused-vars
to report the last reference to a variable that’s not used. See https://github.com/eslint/eslint/issues/13181#issuecomment-619436526 for a case where that change makes much more sense than this.I’m wondering if this is perhaps an unintended side effect of that change. Even in the primary motivating example (demo from the original issue), we report the last reference but not the last assignment. If I were to remove the assignment, the warning would disappear from the reference.
I think the fix here might be to report the last assignment reference instead of just the last reference of any kind. (If there are no assignments, we’d still report the declaration.) Thus in
variable = await variable
, we’d change the rule to report the left side rather than the right, and in this issue’s description, we’d report the declaration rather than the recursive call.Tagging @anikethsaha who made the original improvement. What do you think of my proposed change?
@mdjermanovic yes, I agree with your example there as well. So at least don’t cross function boundaries. What about other scope boundaries? Example:
Demo link
I think in this case I’d be fine warning inside of loops/conditionals and other block-like scopes since flow still proceeds roughly linearly from declaration to their entrance. Functions don’t behave like that, so we shouldn’t warn across function scopes.