]> git.proxmox.com Git - pve-eslint.git/blob - eslint/tests/lib/rules/no-unused-vars.js
first commit
[pve-eslint.git] / eslint / tests / lib / rules / no-unused-vars.js
1 /**
2 * @fileoverview Tests for no-unused-vars rule.
3 * @author Ilya Volodin
4 */
5
6 "use strict";
7
8 //------------------------------------------------------------------------------
9 // Requirements
10 //------------------------------------------------------------------------------
11
12 const rule = require("../../../lib/rules/no-unused-vars"),
13 { RuleTester } = require("../../../lib/rule-tester");
14
15 //------------------------------------------------------------------------------
16 // Tests
17 //------------------------------------------------------------------------------
18
19 const ruleTester = new RuleTester();
20
21 ruleTester.defineRule("use-every-a", context => {
22
23 /**
24 * Mark a variable as used
25 * @returns {void}
26 * @private
27 */
28 function useA() {
29 context.markVariableAsUsed("a");
30 }
31 return {
32 VariableDeclaration: useA,
33 ReturnStatement: useA
34 };
35 });
36
37 /**
38 * Returns an expected error for defined-but-not-used variables.
39 * @param {string} varName The name of the variable
40 * @param {string} [additional] The additional text for the message data
41 * @param {string} [type] The node type (defaults to "Identifier")
42 * @returns {Object} An expected error object
43 */
44 function definedError(varName, additional = "", type = "Identifier") {
45 return {
46 messageId: "unusedVar",
47 data: {
48 varName,
49 action: "defined",
50 additional
51 },
52 type
53 };
54 }
55
56 /**
57 * Returns an expected error for assigned-but-not-used variables.
58 * @param {string} varName The name of the variable
59 * @param {string} [additional] The additional text for the message data
60 * @param {string} [type] The node type (defaults to "Identifier")
61 * @returns {Object} An expected error object
62 */
63 function assignedError(varName, additional = "", type = "Identifier") {
64 return {
65 messageId: "unusedVar",
66 data: {
67 varName,
68 action: "assigned a value",
69 additional
70 },
71 type
72 };
73 }
74
75 ruleTester.run("no-unused-vars", rule, {
76 valid: [
77 "var foo = 5;\n\nlabel: while (true) {\n console.log(foo);\n break label;\n}",
78 "var foo = 5;\n\nwhile (true) {\n console.log(foo);\n break;\n}",
79 { code: "for (let prop in box) {\n box[prop] = parseInt(box[prop]);\n}", parserOptions: { ecmaVersion: 6 } },
80 "var box = {a: 2};\n for (var prop in box) {\n box[prop] = parseInt(box[prop]);\n}",
81 "f({ set foo(a) { return; } });",
82 { code: "a; var a;", options: ["all"] },
83 { code: "var a=10; alert(a);", options: ["all"] },
84 { code: "var a=10; (function() { alert(a); })();", options: ["all"] },
85 { code: "var a=10; (function() { setTimeout(function() { alert(a); }, 0); })();", options: ["all"] },
86 { code: "var a=10; d[a] = 0;", options: ["all"] },
87 { code: "(function() { var a=10; return a; })();", options: ["all"] },
88 { code: "(function g() {})()", options: ["all"] },
89 { code: "function f(a) {alert(a);}; f();", options: ["all"] },
90 { code: "var c = 0; function f(a){ var b = a; return b; }; f(c);", options: ["all"] },
91 { code: "function a(x, y){ return y; }; a();", options: ["all"] },
92 { code: "var arr1 = [1, 2]; var arr2 = [3, 4]; for (var i in arr1) { arr1[i] = 5; } for (var i in arr2) { arr2[i] = 10; }", options: ["all"] },
93 { code: "var a=10;", options: ["local"] },
94 { code: "var min = \"min\"; Math[min];", options: ["all"] },
95 { code: "Foo.bar = function(baz) { return baz; };", options: ["all"] },
96 "myFunc(function foo() {}.bind(this))",
97 "myFunc(function foo(){}.toString())",
98 "function foo(first, second) {\ndoStuff(function() {\nconsole.log(second);});}; foo()",
99 "(function() { var doSomething = function doSomething() {}; doSomething() }())",
100 "try {} catch(e) {}",
101 "/*global a */ a;",
102 { code: "var a=10; (function() { alert(a); })();", options: [{ vars: "all" }] },
103 { code: "function g(bar, baz) { return baz; }; g();", options: [{ vars: "all" }] },
104 { code: "function g(bar, baz) { return baz; }; g();", options: [{ vars: "all", args: "after-used" }] },
105 { code: "function g(bar, baz) { return bar; }; g();", options: [{ vars: "all", args: "none" }] },
106 { code: "function g(bar, baz) { return 2; }; g();", options: [{ vars: "all", args: "none" }] },
107 { code: "function g(bar, baz) { return bar + baz; }; g();", options: [{ vars: "local", args: "all" }] },
108 { code: "var g = function(bar, baz) { return 2; }; g();", options: [{ vars: "all", args: "none" }] },
109 "(function z() { z(); })();",
110 { code: " ", globals: { a: true } },
111 { code: "var who = \"Paul\";\nmodule.exports = `Hello ${who}!`;", parserOptions: { ecmaVersion: 6 } },
112 { code: "export var foo = 123;", parserOptions: { ecmaVersion: 6, sourceType: "module" } },
113 { code: "export function foo () {}", parserOptions: { ecmaVersion: 6, sourceType: "module" } },
114 { code: "let toUpper = (partial) => partial.toUpperCase; export {toUpper}", parserOptions: { ecmaVersion: 6, sourceType: "module" } },
115 { code: "export class foo {}", parserOptions: { ecmaVersion: 6, sourceType: "module" } },
116 { code: "class Foo{}; var x = new Foo(); x.foo()", parserOptions: { ecmaVersion: 6 } },
117 { code: "const foo = \"hello!\";function bar(foobar = foo) { foobar.replace(/!$/, \" world!\");}\nbar();", parserOptions: { ecmaVersion: 6 } },
118 "function Foo(){}; var x = new Foo(); x.foo()",
119 "function foo() {var foo = 1; return foo}; foo();",
120 "function foo(foo) {return foo}; foo(1);",
121 "function foo() {function foo() {return 1;}; return foo()}; foo();",
122 { code: "function foo() {var foo = 1; return foo}; foo();", parserOptions: { parserOptions: { ecmaVersion: 6 } } },
123 { code: "function foo(foo) {return foo}; foo(1);", parserOptions: { parserOptions: { ecmaVersion: 6 } } },
124 { code: "function foo() {function foo() {return 1;}; return foo()}; foo();", parserOptions: { parserOptions: { ecmaVersion: 6 } } },
125 { code: "const x = 1; const [y = x] = []; foo(y);", parserOptions: { ecmaVersion: 6 } },
126 { code: "const x = 1; const {y = x} = {}; foo(y);", parserOptions: { ecmaVersion: 6 } },
127 { code: "const x = 1; const {z: [y = x]} = {}; foo(y);", parserOptions: { ecmaVersion: 6 } },
128 { code: "const x = []; const {z: [y] = x} = {}; foo(y);", parserOptions: { ecmaVersion: 6 } },
129 { code: "const x = 1; let y; [y = x] = []; foo(y);", parserOptions: { ecmaVersion: 6 } },
130 { code: "const x = 1; let y; ({z: [y = x]} = {}); foo(y);", parserOptions: { ecmaVersion: 6 } },
131 { code: "const x = []; let y; ({z: [y] = x} = {}); foo(y);", parserOptions: { ecmaVersion: 6 } },
132 { code: "const x = 1; function foo(y = x) { bar(y); } foo();", parserOptions: { ecmaVersion: 6 } },
133 { code: "const x = 1; function foo({y = x} = {}) { bar(y); } foo();", parserOptions: { ecmaVersion: 6 } },
134 { code: "const x = 1; function foo(y = function(z = x) { bar(z); }) { y(); } foo();", parserOptions: { ecmaVersion: 6 } },
135 { code: "const x = 1; function foo(y = function() { bar(x); }) { y(); } foo();", parserOptions: { ecmaVersion: 6 } },
136 { code: "var x = 1; var [y = x] = []; foo(y);", parserOptions: { ecmaVersion: 6 } },
137 { code: "var x = 1; var {y = x} = {}; foo(y);", parserOptions: { ecmaVersion: 6 } },
138 { code: "var x = 1; var {z: [y = x]} = {}; foo(y);", parserOptions: { ecmaVersion: 6 } },
139 { code: "var x = []; var {z: [y] = x} = {}; foo(y);", parserOptions: { ecmaVersion: 6 } },
140 { code: "var x = 1, y; [y = x] = []; foo(y);", parserOptions: { ecmaVersion: 6 } },
141 { code: "var x = 1, y; ({z: [y = x]} = {}); foo(y);", parserOptions: { ecmaVersion: 6 } },
142 { code: "var x = [], y; ({z: [y] = x} = {}); foo(y);", parserOptions: { ecmaVersion: 6 } },
143 { code: "var x = 1; function foo(y = x) { bar(y); } foo();", parserOptions: { ecmaVersion: 6 } },
144 { code: "var x = 1; function foo({y = x} = {}) { bar(y); } foo();", parserOptions: { ecmaVersion: 6 } },
145 { code: "var x = 1; function foo(y = function(z = x) { bar(z); }) { y(); } foo();", parserOptions: { ecmaVersion: 6 } },
146 { code: "var x = 1; function foo(y = function() { bar(x); }) { y(); } foo();", parserOptions: { ecmaVersion: 6 } },
147
148 // exported variables should work
149 "/*exported toaster*/ var toaster = 'great'",
150 "/*exported toaster, poster*/ var toaster = 1; poster = 0;",
151 { code: "/*exported x*/ var { x } = y", parserOptions: { ecmaVersion: 6 } },
152 { code: "/*exported x, y*/ var { x, y } = z", parserOptions: { ecmaVersion: 6 } },
153
154 // Can mark variables as used via context.markVariableAsUsed()
155 "/*eslint use-every-a:1*/ var a;",
156 "/*eslint use-every-a:1*/ !function(a) { return 1; }",
157 "/*eslint use-every-a:1*/ !function() { var a; return 1 }",
158
159 // ignore pattern
160 { code: "var _a;", options: [{ vars: "all", varsIgnorePattern: "^_" }] },
161 { code: "var a; function foo() { var _b; } foo();", options: [{ vars: "local", varsIgnorePattern: "^_" }] },
162 { code: "function foo(_a) { } foo();", options: [{ args: "all", argsIgnorePattern: "^_" }] },
163 { code: "function foo(a, _b) { return a; } foo();", options: [{ args: "after-used", argsIgnorePattern: "^_" }] },
164 { code: "var [ firstItemIgnored, secondItem ] = items;\nconsole.log(secondItem);", options: [{ vars: "all", varsIgnorePattern: "[iI]gnored" }], parserOptions: { ecmaVersion: 6 } },
165
166 // for-in loops (see #2342)
167 "(function(obj) { var name; for ( name in obj ) return; })({});",
168 "(function(obj) { var name; for ( name in obj ) { return; } })({});",
169 "(function(obj) { for ( var name in obj ) { return true } })({})",
170 "(function(obj) { for ( var name in obj ) return true })({})",
171
172 { code: "(function(obj) { let name; for ( name in obj ) return; })({});", parserOptions: { ecmaVersion: 6 } },
173 { code: "(function(obj) { let name; for ( name in obj ) { return; } })({});", parserOptions: { ecmaVersion: 6 } },
174 { code: "(function(obj) { for ( let name in obj ) { return true } })({})", parserOptions: { ecmaVersion: 6 } },
175 { code: "(function(obj) { for ( let name in obj ) return true })({})", parserOptions: { ecmaVersion: 6 } },
176
177 { code: "(function(obj) { for ( const name in obj ) { return true } })({})", parserOptions: { ecmaVersion: 6 } },
178 { code: "(function(obj) { for ( const name in obj ) return true })({})", parserOptions: { ecmaVersion: 6 } },
179
180 // caughtErrors
181 {
182 code: "try{}catch(err){console.error(err);}",
183 options: [{ caughtErrors: "all" }]
184 },
185 {
186 code: "try{}catch(err){}",
187 options: [{ caughtErrors: "none" }]
188 },
189 {
190 code: "try{}catch(ignoreErr){}",
191 options: [{ caughtErrors: "all", caughtErrorsIgnorePattern: "^ignore" }]
192 },
193
194 // caughtErrors with other combinations
195 {
196 code: "try{}catch(err){}",
197 options: [{ vars: "all", args: "all" }]
198 },
199
200 // Using object rest for variable omission
201 {
202 code: "const data = { type: 'coords', x: 1, y: 2 };\nconst { type, ...coords } = data;\n console.log(coords);",
203 options: [{ ignoreRestSiblings: true }],
204 parserOptions: { ecmaVersion: 2018 }
205 },
206
207 // https://github.com/eslint/eslint/issues/6348
208 "var a = 0, b; b = a = a + 1; foo(b);",
209 "var a = 0, b; b = a += a + 1; foo(b);",
210 "var a = 0, b; b = a++; foo(b);",
211 "function foo(a) { var b = a = a + 1; bar(b) } foo();",
212 "function foo(a) { var b = a += a + 1; bar(b) } foo();",
213 "function foo(a) { var b = a++; bar(b) } foo();",
214
215 // https://github.com/eslint/eslint/issues/6576
216 [
217 "var unregisterFooWatcher;",
218 "// ...",
219 "unregisterFooWatcher = $scope.$watch( \"foo\", function() {",
220 " // ...some code..",
221 " unregisterFooWatcher();",
222 "});"
223 ].join("\n"),
224 [
225 "var ref;",
226 "ref = setInterval(",
227 " function(){",
228 " clearInterval(ref);",
229 " }, 10);"
230 ].join("\n"),
231 [
232 "var _timer;",
233 "function f() {",
234 " _timer = setTimeout(function () {}, _timer ? 100 : 0);",
235 "}",
236 "f();"
237 ].join("\n"),
238 "function foo(cb) { cb = function() { function something(a) { cb(1 + a); } register(something); }(); } foo();",
239 { code: "function* foo(cb) { cb = yield function(a) { cb(1 + a); }; } foo();", parserOptions: { ecmaVersion: 6 } },
240 { code: "function foo(cb) { cb = tag`hello${function(a) { cb(1 + a); }}`; } foo();", parserOptions: { ecmaVersion: 6 } },
241 "function foo(cb) { var b; cb = b = function(a) { cb(1 + a); }; b(); } foo();",
242
243 // https://github.com/eslint/eslint/issues/6646
244 [
245 "function someFunction() {",
246 " var a = 0, i;",
247 " for (i = 0; i < 2; i++) {",
248 " a = myFunction(a);",
249 " }",
250 "}",
251 "someFunction();"
252 ].join("\n"),
253
254 // https://github.com/eslint/eslint/issues/7124
255 {
256 code: "(function(a, b, {c, d}) { d })",
257 options: [{ argsIgnorePattern: "c" }],
258 parserOptions: { ecmaVersion: 6 }
259 },
260 {
261 code: "(function(a, b, {c, d}) { c })",
262 options: [{ argsIgnorePattern: "d" }],
263 parserOptions: { ecmaVersion: 6 }
264 },
265
266 // https://github.com/eslint/eslint/issues/7250
267 {
268 code: "(function(a, b, c) { c })",
269 options: [{ argsIgnorePattern: "c" }]
270 },
271 {
272 code: "(function(a, b, {c, d}) { c })",
273 options: [{ argsIgnorePattern: "[cd]" }],
274 parserOptions: { ecmaVersion: 6 }
275 },
276
277 // https://github.com/eslint/eslint/issues/7351
278 {
279 code: "(class { set foo(UNUSED) {} })",
280 parserOptions: { ecmaVersion: 6 }
281 },
282 {
283 code: "class Foo { set bar(UNUSED) {} } console.log(Foo)",
284 parserOptions: { ecmaVersion: 6 }
285 },
286
287 // https://github.com/eslint/eslint/issues/8119
288 {
289 code: "(({a, ...rest}) => rest)",
290 options: [{ args: "all", ignoreRestSiblings: true }],
291 parserOptions: { ecmaVersion: 2018 }
292 },
293
294 // https://github.com/eslint/eslint/issues/10952
295 "/*eslint use-every-a:1*/ !function(b, a) { return 1 }",
296
297 // https://github.com/eslint/eslint/issues/10982
298 "var a = function () { a(); }; a();",
299 "var a = function(){ return function () { a(); } }; a();",
300 {
301 code: "const a = () => { a(); }; a();",
302 parserOptions: { ecmaVersion: 2015 }
303 },
304 {
305 code: "const a = () => () => { a(); }; a();",
306 parserOptions: { ecmaVersion: 2015 }
307 }
308 ],
309 invalid: [
310 { code: "function foox() { return foox(); }", errors: [definedError("foox")] },
311 { code: "(function() { function foox() { if (true) { return foox(); } } }())", errors: [definedError("foox")] },
312 { code: "var a=10", errors: [assignedError("a")] },
313 { code: "function f() { var a = 1; return function(){ f(a *= 2); }; }", errors: [definedError("f")] },
314 { code: "function f() { var a = 1; return function(){ f(++a); }; }", errors: [definedError("f")] },
315 { code: "/*global a */", errors: [definedError("a", "", "Program")] },
316 { code: "function foo(first, second) {\ndoStuff(function() {\nconsole.log(second);});};", errors: [definedError("foo")] },
317 { code: "var a=10;", options: ["all"], errors: [assignedError("a")] },
318 { code: "var a=10; a=20;", options: ["all"], errors: [assignedError("a")] },
319 { code: "var a=10; (function() { var a = 1; alert(a); })();", options: ["all"], errors: [assignedError("a")] },
320 { code: "var a=10, b=0, c=null; alert(a+b)", options: ["all"], errors: [assignedError("c")] },
321 { code: "var a=10, b=0, c=null; setTimeout(function() { var b=2; alert(a+b+c); }, 0);", options: ["all"], errors: [assignedError("b")] },
322 { code: "var a=10, b=0, c=null; setTimeout(function() { var b=2; var c=2; alert(a+b+c); }, 0);", options: ["all"], errors: [assignedError("b"), assignedError("c")] },
323 { code: "function f(){var a=[];return a.map(function(){});}", options: ["all"], errors: [definedError("f")] },
324 { code: "function f(){var a=[];return a.map(function g(){});}", options: ["all"], errors: [definedError("f")] },
325 {
326 code: "function foo() {function foo(x) {\nreturn x; }; return function() {return foo; }; }",
327 errors: [{
328 messageId: "unusedVar",
329 data: { varName: "foo", action: "defined", additional: "" },
330 line: 1,
331 type: "Identifier"
332 }]
333 },
334 { code: "function f(){var x;function a(){x=42;}function b(){alert(x);}}", options: ["all"], errors: 3 },
335 { code: "function f(a) {}; f();", options: ["all"], errors: [definedError("a")] },
336 { code: "function a(x, y, z){ return y; }; a();", options: ["all"], errors: [definedError("z")] },
337 { code: "var min = Math.min", options: ["all"], errors: [assignedError("min")] },
338 { code: "var min = {min: 1}", options: ["all"], errors: [assignedError("min")] },
339 { code: "Foo.bar = function(baz) { return 1; };", options: ["all"], errors: [definedError("baz")] },
340 { code: "var min = {min: 1}", options: [{ vars: "all" }], errors: [assignedError("min")] },
341 { code: "function gg(baz, bar) { return baz; }; gg();", options: [{ vars: "all" }], errors: [definedError("bar")] },
342 { code: "(function(foo, baz, bar) { return baz; })();", options: [{ vars: "all", args: "after-used" }], errors: [definedError("bar")] },
343 { code: "(function(foo, baz, bar) { return baz; })();", options: [{ vars: "all", args: "all" }], errors: [definedError("foo"), definedError("bar")] },
344 { code: "(function z(foo) { var bar = 33; })();", options: [{ vars: "all", args: "all" }], errors: [definedError("foo"), assignedError("bar")] },
345 { code: "(function z(foo) { z(); })();", options: [{}], errors: [definedError("foo")] },
346 { code: "function f() { var a = 1; return function(){ f(a = 2); }; }", options: [{}], errors: [definedError("f"), assignedError("a")] },
347 { code: "import x from \"y\";", parserOptions: { ecmaVersion: 6, sourceType: "module" }, errors: [definedError("x")] },
348 { code: "export function fn2({ x, y }) {\n console.log(x); \n};", parserOptions: { ecmaVersion: 6, sourceType: "module" }, errors: [definedError("y")] },
349 { code: "export function fn2( x, y ) {\n console.log(x); \n};", parserOptions: { ecmaVersion: 6, sourceType: "module" }, errors: [definedError("y")] },
350
351 // exported
352 { code: "/*exported max*/ var max = 1, min = {min: 1}", errors: [assignedError("min")] },
353 { code: "/*exported x*/ var { x, y } = z", parserOptions: { ecmaVersion: 6 }, errors: [assignedError("y")] },
354
355 // ignore pattern
356 {
357 code: "var _a; var b;",
358 options: [{ vars: "all", varsIgnorePattern: "^_" }],
359 errors: [{
360 line: 1,
361 column: 13,
362 messageId: "unusedVar",
363 data: {
364 varName: "b",
365 action: "defined",
366 additional: ". Allowed unused vars must match /^_/u"
367 }
368 }]
369 },
370 {
371 code: "var a; function foo() { var _b; var c_; } foo();",
372 options: [{ vars: "local", varsIgnorePattern: "^_" }],
373 errors: [{
374 line: 1,
375 column: 37,
376 messageId: "unusedVar",
377 data: {
378 varName: "c_",
379 action: "defined",
380 additional: ". Allowed unused vars must match /^_/u"
381 }
382 }]
383 },
384 {
385 code: "function foo(a, _b) { } foo();",
386 options: [{ args: "all", argsIgnorePattern: "^_" }],
387 errors: [{
388 line: 1,
389 column: 14,
390 messageId: "unusedVar",
391 data: {
392 varName: "a",
393 action: "defined",
394 additional: ". Allowed unused args must match /^_/u"
395 }
396 }]
397 },
398 {
399 code: "function foo(a, _b, c) { return a; } foo();",
400 options: [{ args: "after-used", argsIgnorePattern: "^_" }],
401 errors: [{
402 line: 1,
403 column: 21,
404 messageId: "unusedVar",
405 data: {
406 varName: "c",
407 action: "defined",
408 additional: ". Allowed unused args must match /^_/u"
409 }
410 }]
411 },
412 {
413 code: "function foo(_a) { } foo();",
414 options: [{ args: "all", argsIgnorePattern: "[iI]gnored" }],
415 errors: [{
416 line: 1,
417 column: 14,
418 messageId: "unusedVar",
419 data: {
420 varName: "_a",
421 action: "defined",
422 additional: ". Allowed unused args must match /[iI]gnored/u"
423 }
424 }]
425 },
426 {
427 code: "var [ firstItemIgnored, secondItem ] = items;",
428 options: [{ vars: "all", varsIgnorePattern: "[iI]gnored" }],
429 parserOptions: { ecmaVersion: 6 },
430 errors: [{
431 line: 1,
432 column: 25,
433 messageId: "unusedVar",
434 data: {
435 varName: "secondItem",
436 action: "assigned a value",
437 additional: ". Allowed unused vars must match /[iI]gnored/u"
438 }
439 }]
440 },
441
442 // for-in loops (see #2342)
443 {
444 code: "(function(obj) { var name; for ( name in obj ) { i(); return; } })({});",
445 errors: [{
446 line: 1,
447 column: 22,
448 messageId: "unusedVar",
449 data: {
450 varName: "name",
451 action: "assigned a value",
452 additional: ""
453 }
454 }]
455 },
456 {
457 code: "(function(obj) { var name; for ( name in obj ) { } })({});",
458 errors: [{
459 line: 1,
460 column: 22,
461 messageId: "unusedVar",
462 data: {
463 varName: "name",
464 action: "assigned a value",
465 additional: ""
466 }
467 }]
468 },
469 {
470 code: "(function(obj) { for ( var name in obj ) { } })({});",
471 errors: [{
472 line: 1,
473 column: 28,
474 messageId: "unusedVar",
475 data: {
476 varName: "name",
477 action: "assigned a value",
478 additional: ""
479 }
480 }]
481 },
482
483 // https://github.com/eslint/eslint/issues/3617
484 {
485 code: "\n/* global foobar, foo, bar */\nfoobar;",
486 errors: [
487 {
488 line: 2,
489 endLine: 2,
490 column: 19,
491 endColumn: 22,
492 messageId: "unusedVar",
493 data: {
494 varName: "foo",
495 action: "defined",
496 additional: ""
497 }
498 },
499 {
500 line: 2,
501 endLine: 2,
502 column: 24,
503 endColumn: 27,
504 messageId: "unusedVar",
505 data: {
506 varName: "bar",
507 action: "defined",
508 additional: ""
509 }
510 }
511 ]
512 },
513 {
514 code: "\n/* global foobar,\n foo,\n bar\n */\nfoobar;",
515 errors: [
516 {
517 line: 3,
518 column: 4,
519 endLine: 3,
520 endColumn: 7,
521 messageId: "unusedVar",
522 data: {
523 varName: "foo",
524 action: "defined",
525 additional: ""
526 }
527 },
528 {
529 line: 4,
530 column: 4,
531 endLine: 4,
532 endColumn: 7,
533 messageId: "unusedVar",
534 data: {
535 varName: "bar",
536 action: "defined",
537 additional: ""
538 }
539 }
540 ]
541 },
542
543 // Rest property sibling without ignoreRestSiblings
544 {
545 code: "const data = { type: 'coords', x: 1, y: 2 };\nconst { type, ...coords } = data;\n console.log(coords);",
546 parserOptions: { ecmaVersion: 2018 },
547 errors: [
548 {
549 line: 2,
550 column: 9,
551 messageId: "unusedVar",
552 data: {
553 varName: "type",
554 action: "assigned a value",
555 additional: ""
556 }
557 }
558 ]
559 },
560
561 // Unused rest property with ignoreRestSiblings
562 {
563 code: "const data = { type: 'coords', x: 2, y: 2 };\nconst { type, ...coords } = data;\n console.log(type)",
564 options: [{ ignoreRestSiblings: true }],
565 parserOptions: { ecmaVersion: 2018 },
566 errors: [
567 {
568 line: 2,
569 column: 18,
570 messageId: "unusedVar",
571 data: {
572 varName: "coords",
573 action: "assigned a value",
574 additional: ""
575 }
576 }
577 ]
578 },
579
580 // Unused rest property without ignoreRestSiblings
581 {
582 code: "const data = { type: 'coords', x: 3, y: 2 };\nconst { type, ...coords } = data;\n console.log(type)",
583 parserOptions: { ecmaVersion: 2018 },
584 errors: [
585 {
586 line: 2,
587 column: 18,
588 messageId: "unusedVar",
589 data: {
590 varName: "coords",
591 action: "assigned a value",
592 additional: ""
593 }
594 }
595 ]
596 },
597
598 // Nested array destructuring with rest property
599 {
600 code: "const data = { vars: ['x','y'], x: 1, y: 2 };\nconst { vars: [x], ...coords } = data;\n console.log(coords)",
601 parserOptions: { ecmaVersion: 2018 },
602 errors: [
603 {
604 line: 2,
605 column: 16,
606 messageId: "unusedVar",
607 data: {
608 varName: "x",
609 action: "assigned a value",
610 additional: ""
611 }
612 }
613 ]
614 },
615
616 // Nested object destructuring with rest property
617 {
618 code: "const data = { defaults: { x: 0 }, x: 1, y: 2 };\nconst { defaults: { x }, ...coords } = data;\n console.log(coords)",
619 parserOptions: { ecmaVersion: 2018 },
620 errors: [
621 {
622 line: 2,
623 column: 21,
624 messageId: "unusedVar",
625 data: {
626 varName: "x",
627 action: "assigned a value",
628 additional: ""
629 }
630 }
631 ]
632 },
633
634 // https://github.com/eslint/eslint/issues/8119
635 {
636 code: "(({a, ...rest}) => {})",
637 options: [{ args: "all", ignoreRestSiblings: true }],
638 parserOptions: { ecmaVersion: 2018 },
639 errors: [definedError("rest")]
640 },
641
642 // https://github.com/eslint/eslint/issues/3714
643 {
644 code: "/* global a$fooz,$foo */\na$fooz;",
645 errors: [
646 {
647 line: 1,
648 column: 18,
649 endLine: 1,
650 endColumn: 22,
651 messageId: "unusedVar",
652 data: {
653 varName: "$foo",
654 action: "defined",
655 additional: ""
656 }
657 }
658 ]
659 },
660 {
661 code: "/* globals a$fooz, $ */\na$fooz;",
662 errors: [
663 {
664 line: 1,
665 column: 20,
666 endLine: 1,
667 endColumn: 21,
668 messageId: "unusedVar",
669 data: {
670 varName: "$",
671 action: "defined",
672 additional: ""
673 }
674 }
675 ]
676 },
677 {
678 code: "/*globals $foo*/",
679 errors: [
680 {
681 line: 1,
682 column: 11,
683 endLine: 1,
684 endColumn: 15,
685 messageId: "unusedVar",
686 data: {
687 varName: "$foo",
688 action: "defined",
689 additional: ""
690 }
691 }
692 ]
693 },
694 {
695 code: "/* global global*/",
696 errors: [
697 {
698 line: 1,
699 column: 11,
700 endLine: 1,
701 endColumn: 17,
702 messageId: "unusedVar",
703 data: {
704 varName: "global",
705 action: "defined",
706 additional: ""
707 }
708 }
709 ]
710 },
711 {
712 code: "/*global foo:true*/",
713 errors: [
714 {
715 line: 1,
716 column: 10,
717 endLine: 1,
718 endColumn: 13,
719 messageId: "unusedVar",
720 data: {
721 varName: "foo",
722 action: "defined",
723 additional: ""
724 }
725 }
726 ]
727 },
728
729 // non ascii.
730 {
731 code: "/*global 変数, 数*/\n変数;",
732 errors: [
733 {
734 line: 1,
735 column: 14,
736 endLine: 1,
737 endColumn: 15,
738 messageId: "unusedVar",
739 data: {
740 varName: "æ•°",
741 action: "defined",
742 additional: ""
743 }
744 }
745 ]
746 },
747
748 // surrogate pair.
749 {
750 code: "/*global 𠮷𩸽, 𠮷*/\n\\u{20BB7}\\u{29E3D};",
751 env: { es6: true },
752 errors: [
753 {
754 line: 1,
755 column: 16,
756 endLine: 1,
757 endColumn: 18,
758 messageId: "unusedVar",
759 data: {
760 varName: "ð ®·",
761 action: "defined",
762 additional: ""
763 }
764 }
765 ]
766 },
767
768 // https://github.com/eslint/eslint/issues/4047
769 {
770 code: "export default function(a) {}",
771 parserOptions: { ecmaVersion: 6, sourceType: "module" },
772 errors: [definedError("a")]
773 },
774 {
775 code: "export default function(a, b) { console.log(a); }",
776 parserOptions: { ecmaVersion: 6, sourceType: "module" },
777 errors: [definedError("b")]
778 },
779 {
780 code: "export default (function(a) {});",
781 parserOptions: { ecmaVersion: 6, sourceType: "module" },
782 errors: [definedError("a")]
783 },
784 {
785 code: "export default (function(a, b) { console.log(a); });",
786 parserOptions: { ecmaVersion: 6, sourceType: "module" },
787 errors: [definedError("b")]
788 },
789 {
790 code: "export default (a) => {};",
791 parserOptions: { ecmaVersion: 6, sourceType: "module" },
792 errors: [definedError("a")]
793 },
794 {
795 code: "export default (a, b) => { console.log(a); };",
796 parserOptions: { ecmaVersion: 6, sourceType: "module" },
797 errors: [definedError("b")]
798 },
799
800 // caughtErrors
801 {
802 code: "try{}catch(err){};",
803 options: [{ caughtErrors: "all" }],
804 errors: [definedError("err")]
805 },
806 {
807 code: "try{}catch(err){};",
808 options: [{ caughtErrors: "all", caughtErrorsIgnorePattern: "^ignore" }],
809 errors: [definedError("err", ". Allowed unused args must match /^ignore/u")]
810 },
811
812 // multiple try catch with one success
813 {
814 code: "try{}catch(ignoreErr){}try{}catch(err){};",
815 options: [{ caughtErrors: "all", caughtErrorsIgnorePattern: "^ignore" }],
816 errors: [definedError("err", ". Allowed unused args must match /^ignore/u")]
817 },
818
819 // multiple try catch both fail
820 {
821 code: "try{}catch(error){}try{}catch(err){};",
822 options: [{ caughtErrors: "all", caughtErrorsIgnorePattern: "^ignore" }],
823 errors: [
824 definedError("error", ". Allowed unused args must match /^ignore/u"),
825 definedError("err", ". Allowed unused args must match /^ignore/u")
826 ]
827 },
828
829 // caughtErrors with other configs
830 {
831 code: "try{}catch(err){};",
832 options: [{ vars: "all", args: "all", caughtErrors: "all" }],
833 errors: [definedError("err")]
834 },
835
836 // no conflict in ignore patterns
837 {
838 code: "try{}catch(err){};",
839 options: [
840 {
841 vars: "all",
842 args: "all",
843 caughtErrors: "all",
844 argsIgnorePattern: "^er"
845 }
846 ],
847 errors: [definedError("err")]
848 },
849
850 // Ignore reads for modifications to itself: https://github.com/eslint/eslint/issues/6348
851 { code: "var a = 0; a = a + 1;", errors: [assignedError("a")] },
852 { code: "var a = 0; a = a + a;", errors: [assignedError("a")] },
853 { code: "var a = 0; a += a + 1;", errors: [assignedError("a")] },
854 { code: "var a = 0; a++;", errors: [assignedError("a")] },
855 { code: "function foo(a) { a = a + 1 } foo();", errors: [assignedError("a")] },
856 { code: "function foo(a) { a += a + 1 } foo();", errors: [assignedError("a")] },
857 { code: "function foo(a) { a++ } foo();", errors: [assignedError("a")] },
858 { code: "var a = 3; a = a * 5 + 6;", errors: [assignedError("a")] },
859 { code: "var a = 2, b = 4; a = a * 2 + b;", errors: [assignedError("a")] },
860
861 // https://github.com/eslint/eslint/issues/6576 (For coverage)
862 {
863 code: "function foo(cb) { cb = function(a) { cb(1 + a); }; bar(not_cb); } foo();",
864 errors: [assignedError("cb")]
865 },
866 {
867 code: "function foo(cb) { cb = function(a) { return cb(1 + a); }(); } foo();",
868 errors: [assignedError("cb")]
869 },
870 {
871 code: "function foo(cb) { cb = (function(a) { cb(1 + a); }, cb); } foo();",
872 errors: [assignedError("cb")]
873 },
874 {
875 code: "function foo(cb) { cb = (0, function(a) { cb(1 + a); }); } foo();",
876 errors: [assignedError("cb")]
877 },
878
879 // https://github.com/eslint/eslint/issues/6646
880 {
881 code: [
882 "while (a) {",
883 " function foo(b) {",
884 " b = b + 1;",
885 " }",
886 " foo()",
887 "}"
888 ].join("\n"),
889 errors: [assignedError("b")]
890 },
891
892 // https://github.com/eslint/eslint/issues/7124
893 {
894 code: "(function(a, b, c) {})",
895 options: [{ argsIgnorePattern: "c" }],
896 errors: [
897 definedError("a", ". Allowed unused args must match /c/u"),
898 definedError("b", ". Allowed unused args must match /c/u")
899 ]
900 },
901 {
902 code: "(function(a, b, {c, d}) {})",
903 options: [{ argsIgnorePattern: "[cd]" }],
904 parserOptions: { ecmaVersion: 6 },
905 errors: [
906 definedError("a", ". Allowed unused args must match /[cd]/u"),
907 definedError("b", ". Allowed unused args must match /[cd]/u")
908 ]
909 },
910 {
911 code: "(function(a, b, {c, d}) {})",
912 options: [{ argsIgnorePattern: "c" }],
913 parserOptions: { ecmaVersion: 6 },
914 errors: [
915 definedError("a", ". Allowed unused args must match /c/u"),
916 definedError("b", ". Allowed unused args must match /c/u"),
917 definedError("d", ". Allowed unused args must match /c/u")
918 ]
919 },
920 {
921 code: "(function(a, b, {c, d}) {})",
922 options: [{ argsIgnorePattern: "d" }],
923 parserOptions: { ecmaVersion: 6 },
924 errors: [
925 definedError("a", ". Allowed unused args must match /d/u"),
926 definedError("b", ". Allowed unused args must match /d/u"),
927 definedError("c", ". Allowed unused args must match /d/u")
928 ]
929 },
930 {
931 code: "/*global\rfoo*/",
932 errors: [{
933 line: 2,
934 column: 1,
935 endLine: 2,
936 endColumn: 4,
937 messageId: "unusedVar",
938 data: {
939 varName: "foo",
940 action: "defined",
941 additional: ""
942 }
943 }]
944 },
945
946 // https://github.com/eslint/eslint/issues/8442
947 {
948 code: "(function ({ a }, b ) { return b; })();",
949 parserOptions: { ecmaVersion: 2015 },
950 errors: [
951 definedError("a")
952 ]
953 },
954 {
955 code: "(function ({ a }, { b, c } ) { return b; })();",
956 parserOptions: { ecmaVersion: 2015 },
957 errors: [
958 definedError("a"),
959 definedError("c")
960 ]
961 },
962 {
963 code: "(function ({ a, b }, { c } ) { return b; })();",
964 parserOptions: { ecmaVersion: 2015 },
965 errors: [
966 definedError("a"),
967 definedError("c")
968 ]
969 },
970 {
971 code: "(function ([ a ], b ) { return b; })();",
972 parserOptions: { ecmaVersion: 2015 },
973 errors: [
974 definedError("a")
975 ]
976 },
977 {
978 code: "(function ([ a ], [ b, c ] ) { return b; })();",
979 parserOptions: { ecmaVersion: 2015 },
980 errors: [
981 definedError("a"),
982 definedError("c")
983 ]
984 },
985 {
986 code: "(function ([ a, b ], [ c ] ) { return b; })();",
987 parserOptions: { ecmaVersion: 2015 },
988 errors: [
989 definedError("a"),
990 definedError("c")
991 ]
992 },
993
994 // https://github.com/eslint/eslint/issues/9774
995 {
996 code: "(function(_a) {})();",
997 options: [{ args: "all", varsIgnorePattern: "^_" }],
998 errors: [definedError("_a")]
999 },
1000 {
1001 code: "(function(_a) {})();",
1002 options: [{ args: "all", caughtErrorsIgnorePattern: "^_" }],
1003 errors: [definedError("_a")]
1004 },
1005
1006 // https://github.com/eslint/eslint/issues/10982
1007 {
1008 code: "var a = function() { a(); };",
1009 errors: [assignedError("a")]
1010 },
1011 {
1012 code: "var a = function(){ return function() { a(); } };",
1013 errors: [assignedError("a")]
1014 },
1015 {
1016 code: "const a = () => { a(); };",
1017 parserOptions: { ecmaVersion: 2015 },
1018 errors: [assignedError("a")]
1019 },
1020 {
1021 code: "const a = () => () => { a(); };",
1022 parserOptions: { ecmaVersion: 2015 },
1023 errors: [assignedError("a")]
1024 }
1025 ]
1026 });