Skip to content

Commit

Permalink
Fix: no-unused-vars ignoreRestSiblings check assignments (fixes #14163)…
Browse files Browse the repository at this point in the history
… (#14264)

* Fix: Check assignment reference in no-unused-vars (fixes #14163)

* rename variables

* add example
  • Loading branch information
yeonjuan committed Apr 3, 2021
1 parent b51d077 commit c4d8b0d
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 12 deletions.
7 changes: 5 additions & 2 deletions docs/rules/no-unused-vars.md
Expand Up @@ -214,8 +214,11 @@ Examples of **correct** code for the `{ "ignoreRestSiblings": true }` option:

```js
/*eslint no-unused-vars: ["error", { "ignoreRestSiblings": true }]*/
// 'type' is ignored because it has a rest property sibling.
var { type, ...coords } = data;
// 'foo' and 'bar' were ignored because they have a rest property sibling.
var { foo, ...coords } = data;

var bar;
({ bar, ...coords } = data);
```

### argsIgnorePattern
Expand Down
25 changes: 15 additions & 10 deletions lib/rules/no-unused-vars.js
Expand Up @@ -196,6 +196,17 @@ module.exports = {

}

/**
* Checks whether a node is a sibling of the rest property or not.
* @param {ASTNode} node a node to check
* @returns {boolean} True if the node is a sibling of the rest property, otherwise false.
*/
function hasRestSibling(node) {
return node.type === "Property" &&
node.parent.type === "ObjectPattern" &&
REST_PROPERTY_TYPE.test(node.parent.properties[node.parent.properties.length - 1].type);
}

/**
* Determines if a variable has a sibling rest property
* @param {Variable} variable eslint-scope variable object.
Expand All @@ -204,16 +215,10 @@ module.exports = {
*/
function hasRestSpreadSibling(variable) {
if (config.ignoreRestSiblings) {
return variable.defs.some(def => {
const propertyNode = def.name.parent;
const patternNode = propertyNode.parent;

return (
propertyNode.type === "Property" &&
patternNode.type === "ObjectPattern" &&
REST_PROPERTY_TYPE.test(patternNode.properties[patternNode.properties.length - 1].type)
);
});
const hasRestSiblingDefinition = variable.defs.some(def => hasRestSibling(def.name.parent));
const hasRestSiblingReference = variable.references.some(ref => hasRestSibling(ref.identifier.parent));

return hasRestSiblingDefinition || hasRestSiblingReference;
}

return false;
Expand Down
24 changes: 24 additions & 0 deletions tests/lib/rules/no-unused-vars.js
Expand Up @@ -291,6 +291,13 @@ ruleTester.run("no-unused-vars", rule, {
parserOptions: { ecmaVersion: 2018 }
},

// https://github.com/eslint/eslint/issues/14163
{
code: "let foo, rest;\n({ foo, ...rest } = something);\nconsole.log(rest);",
options: [{ ignoreRestSiblings: true }],
parserOptions: { ecmaVersion: 2020 }
},

// https://github.com/eslint/eslint/issues/10952
"/*eslint use-every-a:1*/ !function(b, a) { return 1 }",

Expand Down Expand Up @@ -588,6 +595,23 @@ ruleTester.run("no-unused-vars", rule, {
}
]
},
{
code: "let type, coords;\n({ type, ...coords } = data);\n console.log(type)",
options: [{ ignoreRestSiblings: true }],
parserOptions: { ecmaVersion: 2018 },
errors: [
{
line: 2,
column: 13,
messageId: "unusedVar",
data: {
varName: "coords",
action: "assigned a value",
additional: ""
}
}
]
},

// Unused rest property without ignoreRestSiblings
{
Expand Down

0 comments on commit c4d8b0d

Please sign in to comment.