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 destructuredArrayIgnorePattern option in no-unused-vars #15649

Merged
merged 15 commits into from Mar 11, 2022
14 changes: 14 additions & 0 deletions docs/rules/no-unused-vars.md
Expand Up @@ -238,6 +238,20 @@ function foo(x, _y) {
foo();
```

### destructuredArrayIgnorePattern

The `destructuredArrayIgnorePattern` option specifies exceptions not to check for usage: destructuring assignments from an array whose names match a regexp pattern. For example, variables whose names begin with an underscore.
snitin315 marked this conversation as resolved.
Show resolved Hide resolved

Examples of **correct** code for the `{ "destructuredArrayIgnorePattern": "^_" }` option:

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

const [a, _b, c] = ["a", "b", "c"]

console.log(a + c);
```

### caughtErrors

The `caughtErrors` option is used for `catch` block arguments validation.
Expand Down
23 changes: 22 additions & 1 deletion lib/rules/no-unused-vars.js
Expand Up @@ -67,6 +67,9 @@ module.exports = {
},
caughtErrorsIgnorePattern: {
type: "string"
},
destructuredArrayIgnorePattern: {
type: "string"
}
},
additionalProperties: false
Expand Down Expand Up @@ -114,6 +117,10 @@ module.exports = {
if (firstOption.caughtErrorsIgnorePattern) {
config.caughtErrorsIgnorePattern = new RegExp(firstOption.caughtErrorsIgnorePattern, "u");
}

if (firstOption.destructuredArrayIgnorePattern) {
config.destructuredArrayIgnorePattern = new RegExp(firstOption.destructuredArrayIgnorePattern, "u");
}
}
}

Expand Down Expand Up @@ -155,7 +162,16 @@ module.exports = {
* @returns {UnusedVarMessageData} The message data to be used with this unused variable.
*/
function getAssignedMessageData(unusedVar) {
const additional = config.varsIgnorePattern ? `. Allowed unused vars must match ${config.varsIgnorePattern.toString()}` : "";
const def = unusedVar.defs && unusedVar.defs[0];
snitin315 marked this conversation as resolved.
Show resolved Hide resolved
let patternToMatch;

if (config.destructuredArrayIgnorePattern && def.type === "Variable" && def.node.id.type === "ArrayPattern") {
patternToMatch = config.destructuredArrayIgnorePattern;
} else if (config.varsIgnorePattern) {
patternToMatch = config.varsIgnorePattern;
}

const additional = patternToMatch ? `. Allowed unused vars must match ${patternToMatch.toString()}` : "";
snitin315 marked this conversation as resolved.
Show resolved Hide resolved

return {
varName: unusedVar.name,
Expand Down Expand Up @@ -624,6 +640,11 @@ module.exports = {
if (config.varsIgnorePattern && config.varsIgnorePattern.test(def.name.name)) {
continue;
}

// https://github.com/eslint/eslint/issues/15611
snitin315 marked this conversation as resolved.
Show resolved Hide resolved
if (type === "Variable" && def.node.id.type === "ArrayPattern" && config.destructuredArrayIgnorePattern && config.destructuredArrayIgnorePattern.test(def.name.name)) {
snitin315 marked this conversation as resolved.
Show resolved Hide resolved
continue;
}
}
}

Expand Down
72 changes: 72 additions & 0 deletions tests/lib/rules/no-unused-vars.js
Expand Up @@ -163,6 +163,9 @@ ruleTester.run("no-unused-vars", rule, {
{ code: "function foo(a, _b) { return a; } foo();", options: [{ args: "after-used", argsIgnorePattern: "^_" }] },
{ code: "var [ firstItemIgnored, secondItem ] = items;\nconsole.log(secondItem);", options: [{ vars: "all", varsIgnorePattern: "[iI]gnored" }], parserOptions: { ecmaVersion: 6 } },

// https://github.com/eslint/eslint/issues/15611
{ code: "const [ a, _b, c ] = items;\nconsole.log(a+c);", options: [{ destructuredArrayIgnorePattern: "^_" }], parserOptions: { ecmaVersion: 6 } },

// for-in loops (see #2342)
"(function(obj) { var name; for ( name in obj ) return; })({});",
"(function(obj) { var name; for ( name in obj ) { return; } })({});",
Expand Down Expand Up @@ -463,6 +466,75 @@ ruleTester.run("no-unused-vars", rule, {
}]
},

// https://github.com/eslint/eslint/issues/15611
{
code: `
const array = ['a', 'b', 'c'];
const [a, _b, c] = array;
const newArray = [a, c];
`,
options: [{ destructuredArrayIgnorePattern: "^_" }],
parserOptions: { ecmaVersion: 2020 },
errors: [

// should report only `newArray`
{ ...assignedError("newArray"), line: 4, column: 19 }
]
},
{
code: `
const array = ['a', 'b', 'c', 'd', 'e'];
const [a, _b, c] = array;
`,
options: [{ destructuredArrayIgnorePattern: "^_" }],
parserOptions: { ecmaVersion: 2020 },
errors: [
{
...assignedError("a", ". Allowed unused vars must match /^_/u"),
line: 3,
column: 20
},
{
...assignedError("c", ". Allowed unused vars must match /^_/u"),
line: 3,
column: 27
}
]
},
{
code: `
const array = ['a', 'b', 'c'];
const [a, _b, c] = array;
const fooArray = ['foo'];
const barArray = ['bar'];
const ignoreArray = ['ignore'];
`,
options: [{ destructuredArrayIgnorePattern: "^_", varsIgnorePattern: "ignore" }],
parserOptions: { ecmaVersion: 2020 },
errors: [
{
...assignedError("a", ". Allowed unused vars must match /^_/u"),
line: 3,
column: 20
},
{
...assignedError("c", ". Allowed unused vars must match /^_/u"),
line: 3,
column: 27
},
{
...assignedError("fooArray", ". Allowed unused vars must match /ignore/u"),
line: 4,
column: 19
},
{
...assignedError("barArray", ". Allowed unused vars must match /ignore/u"),
line: 5,
column: 19
}
]
},

// for-in loops (see #2342)
{
code: "(function(obj) { var name; for ( name in obj ) { i(); return; } })({});",
Expand Down