Skip to content

Commit 91fc1c5

Browse files
committed
Update: add new ignore pattern options to no-unused-vars (fixes #2321)
1 parent 832a22a commit 91fc1c5

3 files changed

Lines changed: 107 additions & 21 deletions

File tree

docs/rules/no-unused-vars.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,51 @@ The following code:
9898
})();
9999
```
100100

101+
#### Ignore identifiers that match specific patterns
102+
103+
* `varsIgnorePattern` - all variables that match this regexp pattern will not be checked.
104+
* `argsIgnorePattern` - all arguments that match this regexp pattern will not be checked.
105+
106+
##### Examples
107+
108+
* Ignore all unused function arguments with a leading underscore
109+
110+
```json
111+
{
112+
"rules": {
113+
"no-unused-vars": [2, {"args": "after-used", "argsIgnorePattern": "^_"}]
114+
}
115+
}
116+
```
117+
118+
With this configuration, this rule will not warn about the following code:
119+
120+
```js
121+
function foo(x, _y) {
122+
return x + 1;
123+
}
124+
foo();
125+
```
126+
127+
* Ignore all unused variables which contain the term `ignored` or `Ignored`:
128+
129+
```json
130+
{
131+
"ecmaFeatures": { "destructuring": true },
132+
"rules": {
133+
"no-unused-vars": [2, {"vars": "all", "varsIgnorePattern": "[iI]gnored"}]
134+
}
135+
}
136+
```
137+
138+
With this configuration, this rule will not warn about the following code:
139+
140+
```js
141+
var [ firstItemIgnored, secondItem ] = items;
142+
console.log(secondItem);
143+
```
144+
145+
101146
## When Not to Use It
102147

103148
If you don't want to be notified about unused variables or function arguments, you can safely turn this rule off.

lib/rules/no-unused-vars.js

Lines changed: 46 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,29 @@ module.exports = function(context) {
1818
args: "after-used"
1919
};
2020

21-
if (context.options[0]) {
22-
if (typeof context.options[0] === "string") {
23-
config.vars = context.options[0];
21+
var firstOption = context.options[0];
22+
23+
if (firstOption) {
24+
if (typeof firstOption === "string") {
25+
config.vars = firstOption;
2426
} else {
25-
config.vars = context.options[0].vars || config.vars;
26-
config.args = context.options[0].args || config.args;
27+
config.vars = firstOption.vars || config.vars;
28+
config.args = firstOption.args || config.args;
29+
30+
if (firstOption.varsIgnorePattern) {
31+
config.varsIgnorePattern = new RegExp(firstOption.varsIgnorePattern);
32+
}
33+
34+
if (firstOption.argsIgnorePattern) {
35+
config.argsIgnorePattern = new RegExp(firstOption.argsIgnorePattern);
36+
}
2737
}
2838
}
2939

3040
//--------------------------------------------------------------------------
3141
// Helpers
3242
//--------------------------------------------------------------------------
3343

34-
3544
/**
3645
* Determines if a given variable is being exported from a module.
3746
* @param {Variable} variable - EScope variable object.
@@ -175,19 +184,31 @@ module.exports = function(context) {
175184
continue;
176185
}
177186

178-
// skip any setter argument
179-
if (type === "Parameter" && def.node.parent.type === "Property" && def.node.parent.kind === "set") {
180-
continue;
181-
}
182-
183-
// if "args" option is "none", skip any parameter
184-
if (config.args === "none" && type === "Parameter") {
185-
continue;
186-
}
187-
188-
// if "args" option is "after-used", skip all but the last parameter
189-
if (config.args === "after-used" && type === "Parameter" && def.index < def.node.params.length - 1) {
190-
continue;
187+
if (type === "Parameter") {
188+
// skip any setter argument
189+
if (def.node.parent.type === "Property" && def.node.parent.kind === "set") {
190+
continue;
191+
}
192+
193+
// if "args" option is "none", skip any parameter
194+
if (config.args === "none") {
195+
continue;
196+
}
197+
198+
// skip ignored parameters
199+
if (config.argsIgnorePattern && config.argsIgnorePattern.test(def.name.name)) {
200+
continue;
201+
}
202+
203+
// if "args" option is "after-used", skip all but the last parameter
204+
if (config.args === "after-used" && def.index < def.node.params.length - 1) {
205+
continue;
206+
}
207+
} else {
208+
// skip ignored variables
209+
if (config.varsIgnorePattern && config.varsIgnorePattern.test(def.name.name)) {
210+
continue;
211+
}
191212
}
192213
}
193214

@@ -244,8 +265,14 @@ module.exports.schema = [
244265
"vars": {
245266
"enum": ["all", "local"]
246267
},
268+
"varsIgnorePattern": {
269+
"type": "string"
270+
},
247271
"args": {
248272
"enum": ["all", "after-used", "none"]
273+
},
274+
"argsIgnorePattern": {
275+
"type": "string"
249276
}
250277
}
251278
}

tests/lib/rules/no-unused-vars.js

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,14 @@ ruleTester.run("no-unused-vars", rule, {
111111
// Can mark variables as used via context.markVariableAsUsed()
112112
{ code: "/*eslint use-every-a:1*/ var a;"},
113113
{ code: "/*eslint use-every-a:1*/ !function(a) { return 1; }"},
114-
{ code: "/*eslint use-every-a:1*/ !function() { var a; return 1 }"}
114+
{ code: "/*eslint use-every-a:1*/ !function() { var a; return 1 }"},
115+
116+
// ignore pattern
117+
{ code: "var _a;", options: [ { vars: "all", varsIgnorePattern: "^_" } ] },
118+
{ code: "var a; function foo() { var _b; } foo();", options: [ { vars: "local", varsIgnorePattern: "^_" } ] },
119+
{ code: "function foo(_a) { } foo();", options: [ { args: "all", argsIgnorePattern: "^_" } ] },
120+
{ code: "function foo(a, _b) { return a; } foo();", options: [ { args: "after-used", argsIgnorePattern: "^_" } ] },
121+
{ code: "var [ firstItemIgnored, secondItem ] = items;\nconsole.log(secondItem);", ecmaFeatures: {destructuring: true}, options: [ { vars: "all", varsIgnorePattern: "[iI]gnored" } ] }
115122
],
116123
invalid: [
117124
{ code: "function foox() { return foox(); }", errors: [{ message: "foox is defined but never used", type: "Identifier"}] },
@@ -149,6 +156,13 @@ ruleTester.run("no-unused-vars", rule, {
149156

150157
// exported
151158
{ code: "/*exported max*/ var max = 1, min = {min: 1}", errors: [{ message: "min is defined but never used" }] },
152-
{ code: "/*exported x*/ var { x, y } = z", ecmaFeatures: { destructuring: true }, errors: [{ message: "y is defined but never used" }] }
159+
{ code: "/*exported x*/ var { x, y } = z", ecmaFeatures: { destructuring: true }, errors: [{ message: "y is defined but never used" }] },
160+
161+
// ignore pattern
162+
{ code: "var _a; var b;", options: [ { vars: "all", varsIgnorePattern: "^_" } ], errors: [{ message: "b is defined but never used", line: 1, column: 13 }] },
163+
{ code: "var a; function foo() { var _b; var c_; } foo();", options: [ { vars: "local", varsIgnorePattern: "^_" } ], errors: [{ message: "c_ is defined but never used", line: 1, column: 37 }] },
164+
{ code: "function foo(a, _b) { } foo();", options: [ { args: "all", argsIgnorePattern: "^_" } ], errors: [{ message: "a is defined but never used", line: 1, column: 14 }] },
165+
{ code: "function foo(a, _b, c) { return a; } foo();", options: [ { args: "after-used", argsIgnorePattern: "^_" } ], errors: [{ message: "c is defined but never used", line: 1, column: 21 }] },
166+
{ code: "var [ firstItemIgnored, secondItem ] = items;", ecmaFeatures: {destructuring: true}, options: [ { vars: "all", varsIgnorePattern: "[iI]gnored" } ], errors: [{ message: "secondItem is defined but never used", line: 1, column: 25 }] }
153167
]
154168
});

0 commit comments

Comments
 (0)