]> git.proxmox.com Git - pve-eslint.git/blob - eslint/tests/lib/rules/no-unused-vars.js
48ccdb1d42ff9ad8517435062a1dfd7e41b7633d
[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 // Sequence Expressions (See https://github.com/eslint/eslint/issues/14325)
181 { code: "let x = 0; foo = (0, x++);", parserOptions: { ecmaVersion: 6 } },
182 { code: "let x = 0; foo = (0, x += 1);", parserOptions: { ecmaVersion: 6 } },
183
184 // caughtErrors
185 {
186 code: "try{}catch(err){console.error(err);}",
187 options: [{ caughtErrors: "all" }]
188 },
189 {
190 code: "try{}catch(err){}",
191 options: [{ caughtErrors: "none" }]
192 },
193 {
194 code: "try{}catch(ignoreErr){}",
195 options: [{ caughtErrors: "all", caughtErrorsIgnorePattern: "^ignore" }]
196 },
197
198 // caughtErrors with other combinations
199 {
200 code: "try{}catch(err){}",
201 options: [{ vars: "all", args: "all" }]
202 },
203
204 // Using object rest for variable omission
205 {
206 code: "const data = { type: 'coords', x: 1, y: 2 };\nconst { type, ...coords } = data;\n console.log(coords);",
207 options: [{ ignoreRestSiblings: true }],
208 parserOptions: { ecmaVersion: 2018 }
209 },
210
211 // https://github.com/eslint/eslint/issues/6348
212 "var a = 0, b; b = a = a + 1; foo(b);",
213 "var a = 0, b; b = a += a + 1; foo(b);",
214 "var a = 0, b; b = a++; foo(b);",
215 "function foo(a) { var b = a = a + 1; bar(b) } foo();",
216 "function foo(a) { var b = a += a + 1; bar(b) } foo();",
217 "function foo(a) { var b = a++; bar(b) } foo();",
218
219 // https://github.com/eslint/eslint/issues/6576
220 [
221 "var unregisterFooWatcher;",
222 "// ...",
223 "unregisterFooWatcher = $scope.$watch( \"foo\", function() {",
224 " // ...some code..",
225 " unregisterFooWatcher();",
226 "});"
227 ].join("\n"),
228 [
229 "var ref;",
230 "ref = setInterval(",
231 " function(){",
232 " clearInterval(ref);",
233 " }, 10);"
234 ].join("\n"),
235 [
236 "var _timer;",
237 "function f() {",
238 " _timer = setTimeout(function () {}, _timer ? 100 : 0);",
239 "}",
240 "f();"
241 ].join("\n"),
242 "function foo(cb) { cb = function() { function something(a) { cb(1 + a); } register(something); }(); } foo();",
243 { code: "function* foo(cb) { cb = yield function(a) { cb(1 + a); }; } foo();", parserOptions: { ecmaVersion: 6 } },
244 { code: "function foo(cb) { cb = tag`hello${function(a) { cb(1 + a); }}`; } foo();", parserOptions: { ecmaVersion: 6 } },
245 "function foo(cb) { var b; cb = b = function(a) { cb(1 + a); }; b(); } foo();",
246
247 // https://github.com/eslint/eslint/issues/6646
248 [
249 "function someFunction() {",
250 " var a = 0, i;",
251 " for (i = 0; i < 2; i++) {",
252 " a = myFunction(a);",
253 " }",
254 "}",
255 "someFunction();"
256 ].join("\n"),
257
258 // https://github.com/eslint/eslint/issues/7124
259 {
260 code: "(function(a, b, {c, d}) { d })",
261 options: [{ argsIgnorePattern: "c" }],
262 parserOptions: { ecmaVersion: 6 }
263 },
264 {
265 code: "(function(a, b, {c, d}) { c })",
266 options: [{ argsIgnorePattern: "d" }],
267 parserOptions: { ecmaVersion: 6 }
268 },
269
270 // https://github.com/eslint/eslint/issues/7250
271 {
272 code: "(function(a, b, c) { c })",
273 options: [{ argsIgnorePattern: "c" }]
274 },
275 {
276 code: "(function(a, b, {c, d}) { c })",
277 options: [{ argsIgnorePattern: "[cd]" }],
278 parserOptions: { ecmaVersion: 6 }
279 },
280
281 // https://github.com/eslint/eslint/issues/7351
282 {
283 code: "(class { set foo(UNUSED) {} })",
284 parserOptions: { ecmaVersion: 6 }
285 },
286 {
287 code: "class Foo { set bar(UNUSED) {} } console.log(Foo)",
288 parserOptions: { ecmaVersion: 6 }
289 },
290
291 // https://github.com/eslint/eslint/issues/8119
292 {
293 code: "(({a, ...rest}) => rest)",
294 options: [{ args: "all", ignoreRestSiblings: true }],
295 parserOptions: { ecmaVersion: 2018 }
296 },
297
298 // https://github.com/eslint/eslint/issues/14163
299 {
300 code: "let foo, rest;\n({ foo, ...rest } = something);\nconsole.log(rest);",
301 options: [{ ignoreRestSiblings: true }],
302 parserOptions: { ecmaVersion: 2020 }
303 },
304
305 // https://github.com/eslint/eslint/issues/10952
306 "/*eslint use-every-a:1*/ !function(b, a) { return 1 }",
307
308 // https://github.com/eslint/eslint/issues/10982
309 "var a = function () { a(); }; a();",
310 "var a = function(){ return function () { a(); } }; a();",
311 {
312 code: "const a = () => { a(); }; a();",
313 parserOptions: { ecmaVersion: 2015 }
314 },
315 {
316 code: "const a = () => () => { a(); }; a();",
317 parserOptions: { ecmaVersion: 2015 }
318 },
319
320 // export * as ns from "source"
321 {
322 code: 'export * as ns from "source"',
323 parserOptions: { ecmaVersion: 2020, sourceType: "module" }
324 },
325
326 // import.meta
327 {
328 code: "import.meta",
329 parserOptions: { ecmaVersion: 2020, sourceType: "module" }
330 }
331 ],
332 invalid: [
333 { code: "function foox() { return foox(); }", errors: [definedError("foox")] },
334 { code: "(function() { function foox() { if (true) { return foox(); } } }())", errors: [definedError("foox")] },
335 { code: "var a=10", errors: [assignedError("a")] },
336 { code: "function f() { var a = 1; return function(){ f(a *= 2); }; }", errors: [definedError("f")] },
337 { code: "function f() { var a = 1; return function(){ f(++a); }; }", errors: [definedError("f")] },
338 { code: "/*global a */", errors: [definedError("a", "", "Program")] },
339 { code: "function foo(first, second) {\ndoStuff(function() {\nconsole.log(second);});};", errors: [definedError("foo")] },
340 { code: "var a=10;", options: ["all"], errors: [assignedError("a")] },
341 { code: "var a=10; a=20;", options: ["all"], errors: [assignedError("a")] },
342 { code: "var a=10; (function() { var a = 1; alert(a); })();", options: ["all"], errors: [assignedError("a")] },
343 { code: "var a=10, b=0, c=null; alert(a+b)", options: ["all"], errors: [assignedError("c")] },
344 { code: "var a=10, b=0, c=null; setTimeout(function() { var b=2; alert(a+b+c); }, 0);", options: ["all"], errors: [assignedError("b")] },
345 { 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")] },
346 { code: "function f(){var a=[];return a.map(function(){});}", options: ["all"], errors: [definedError("f")] },
347 { code: "function f(){var a=[];return a.map(function g(){});}", options: ["all"], errors: [definedError("f")] },
348 {
349 code: "function foo() {function foo(x) {\nreturn x; }; return function() {return foo; }; }",
350 errors: [{
351 messageId: "unusedVar",
352 data: { varName: "foo", action: "defined", additional: "" },
353 line: 1,
354 type: "Identifier"
355 }]
356 },
357 { code: "function f(){var x;function a(){x=42;}function b(){alert(x);}}", options: ["all"], errors: 3 },
358 { code: "function f(a) {}; f();", options: ["all"], errors: [definedError("a")] },
359 { code: "function a(x, y, z){ return y; }; a();", options: ["all"], errors: [definedError("z")] },
360 { code: "var min = Math.min", options: ["all"], errors: [assignedError("min")] },
361 { code: "var min = {min: 1}", options: ["all"], errors: [assignedError("min")] },
362 { code: "Foo.bar = function(baz) { return 1; };", options: ["all"], errors: [definedError("baz")] },
363 { code: "var min = {min: 1}", options: [{ vars: "all" }], errors: [assignedError("min")] },
364 { code: "function gg(baz, bar) { return baz; }; gg();", options: [{ vars: "all" }], errors: [definedError("bar")] },
365 { code: "(function(foo, baz, bar) { return baz; })();", options: [{ vars: "all", args: "after-used" }], errors: [definedError("bar")] },
366 { code: "(function(foo, baz, bar) { return baz; })();", options: [{ vars: "all", args: "all" }], errors: [definedError("foo"), definedError("bar")] },
367 { code: "(function z(foo) { var bar = 33; })();", options: [{ vars: "all", args: "all" }], errors: [definedError("foo"), assignedError("bar")] },
368 { code: "(function z(foo) { z(); })();", options: [{}], errors: [definedError("foo")] },
369 { code: "function f() { var a = 1; return function(){ f(a = 2); }; }", options: [{}], errors: [definedError("f"), assignedError("a")] },
370 { code: "import x from \"y\";", parserOptions: { ecmaVersion: 6, sourceType: "module" }, errors: [definedError("x")] },
371 { code: "export function fn2({ x, y }) {\n console.log(x); \n};", parserOptions: { ecmaVersion: 6, sourceType: "module" }, errors: [definedError("y")] },
372 { code: "export function fn2( x, y ) {\n console.log(x); \n};", parserOptions: { ecmaVersion: 6, sourceType: "module" }, errors: [definedError("y")] },
373
374 // exported
375 { code: "/*exported max*/ var max = 1, min = {min: 1}", errors: [assignedError("min")] },
376 { code: "/*exported x*/ var { x, y } = z", parserOptions: { ecmaVersion: 6 }, errors: [assignedError("y")] },
377
378 // ignore pattern
379 {
380 code: "var _a; var b;",
381 options: [{ vars: "all", varsIgnorePattern: "^_" }],
382 errors: [{
383 line: 1,
384 column: 13,
385 messageId: "unusedVar",
386 data: {
387 varName: "b",
388 action: "defined",
389 additional: ". Allowed unused vars must match /^_/u"
390 }
391 }]
392 },
393 {
394 code: "var a; function foo() { var _b; var c_; } foo();",
395 options: [{ vars: "local", varsIgnorePattern: "^_" }],
396 errors: [{
397 line: 1,
398 column: 37,
399 messageId: "unusedVar",
400 data: {
401 varName: "c_",
402 action: "defined",
403 additional: ". Allowed unused vars must match /^_/u"
404 }
405 }]
406 },
407 {
408 code: "function foo(a, _b) { } foo();",
409 options: [{ args: "all", argsIgnorePattern: "^_" }],
410 errors: [{
411 line: 1,
412 column: 14,
413 messageId: "unusedVar",
414 data: {
415 varName: "a",
416 action: "defined",
417 additional: ". Allowed unused args must match /^_/u"
418 }
419 }]
420 },
421 {
422 code: "function foo(a, _b, c) { return a; } foo();",
423 options: [{ args: "after-used", argsIgnorePattern: "^_" }],
424 errors: [{
425 line: 1,
426 column: 21,
427 messageId: "unusedVar",
428 data: {
429 varName: "c",
430 action: "defined",
431 additional: ". Allowed unused args must match /^_/u"
432 }
433 }]
434 },
435 {
436 code: "function foo(_a) { } foo();",
437 options: [{ args: "all", argsIgnorePattern: "[iI]gnored" }],
438 errors: [{
439 line: 1,
440 column: 14,
441 messageId: "unusedVar",
442 data: {
443 varName: "_a",
444 action: "defined",
445 additional: ". Allowed unused args must match /[iI]gnored/u"
446 }
447 }]
448 },
449 {
450 code: "var [ firstItemIgnored, secondItem ] = items;",
451 options: [{ vars: "all", varsIgnorePattern: "[iI]gnored" }],
452 parserOptions: { ecmaVersion: 6 },
453 errors: [{
454 line: 1,
455 column: 25,
456 messageId: "unusedVar",
457 data: {
458 varName: "secondItem",
459 action: "assigned a value",
460 additional: ". Allowed unused vars must match /[iI]gnored/u"
461 }
462 }]
463 },
464
465 // for-in loops (see #2342)
466 {
467 code: "(function(obj) { var name; for ( name in obj ) { i(); return; } })({});",
468 errors: [{
469 line: 1,
470 column: 34,
471 messageId: "unusedVar",
472 data: {
473 varName: "name",
474 action: "assigned a value",
475 additional: ""
476 }
477 }]
478 },
479 {
480 code: "(function(obj) { var name; for ( name in obj ) { } })({});",
481 errors: [{
482 line: 1,
483 column: 34,
484 messageId: "unusedVar",
485 data: {
486 varName: "name",
487 action: "assigned a value",
488 additional: ""
489 }
490 }]
491 },
492 {
493 code: "(function(obj) { for ( var name in obj ) { } })({});",
494 errors: [{
495 line: 1,
496 column: 28,
497 messageId: "unusedVar",
498 data: {
499 varName: "name",
500 action: "assigned a value",
501 additional: ""
502 }
503 }]
504 },
505
506 // https://github.com/eslint/eslint/issues/3617
507 {
508 code: "\n/* global foobar, foo, bar */\nfoobar;",
509 errors: [
510 {
511 line: 2,
512 endLine: 2,
513 column: 19,
514 endColumn: 22,
515 messageId: "unusedVar",
516 data: {
517 varName: "foo",
518 action: "defined",
519 additional: ""
520 }
521 },
522 {
523 line: 2,
524 endLine: 2,
525 column: 24,
526 endColumn: 27,
527 messageId: "unusedVar",
528 data: {
529 varName: "bar",
530 action: "defined",
531 additional: ""
532 }
533 }
534 ]
535 },
536 {
537 code: "\n/* global foobar,\n foo,\n bar\n */\nfoobar;",
538 errors: [
539 {
540 line: 3,
541 column: 4,
542 endLine: 3,
543 endColumn: 7,
544 messageId: "unusedVar",
545 data: {
546 varName: "foo",
547 action: "defined",
548 additional: ""
549 }
550 },
551 {
552 line: 4,
553 column: 4,
554 endLine: 4,
555 endColumn: 7,
556 messageId: "unusedVar",
557 data: {
558 varName: "bar",
559 action: "defined",
560 additional: ""
561 }
562 }
563 ]
564 },
565
566 // Rest property sibling without ignoreRestSiblings
567 {
568 code: "const data = { type: 'coords', x: 1, y: 2 };\nconst { type, ...coords } = data;\n console.log(coords);",
569 parserOptions: { ecmaVersion: 2018 },
570 errors: [
571 {
572 line: 2,
573 column: 9,
574 messageId: "unusedVar",
575 data: {
576 varName: "type",
577 action: "assigned a value",
578 additional: ""
579 }
580 }
581 ]
582 },
583
584 // Unused rest property with ignoreRestSiblings
585 {
586 code: "const data = { type: 'coords', x: 2, y: 2 };\nconst { type, ...coords } = data;\n console.log(type)",
587 options: [{ ignoreRestSiblings: true }],
588 parserOptions: { ecmaVersion: 2018 },
589 errors: [
590 {
591 line: 2,
592 column: 18,
593 messageId: "unusedVar",
594 data: {
595 varName: "coords",
596 action: "assigned a value",
597 additional: ""
598 }
599 }
600 ]
601 },
602 {
603 code: "let type, coords;\n({ type, ...coords } = data);\n console.log(type)",
604 options: [{ ignoreRestSiblings: true }],
605 parserOptions: { ecmaVersion: 2018 },
606 errors: [
607 {
608 line: 2,
609 column: 13,
610 messageId: "unusedVar",
611 data: {
612 varName: "coords",
613 action: "assigned a value",
614 additional: ""
615 }
616 }
617 ]
618 },
619
620 // Unused rest property without ignoreRestSiblings
621 {
622 code: "const data = { type: 'coords', x: 3, y: 2 };\nconst { type, ...coords } = data;\n console.log(type)",
623 parserOptions: { ecmaVersion: 2018 },
624 errors: [
625 {
626 line: 2,
627 column: 18,
628 messageId: "unusedVar",
629 data: {
630 varName: "coords",
631 action: "assigned a value",
632 additional: ""
633 }
634 }
635 ]
636 },
637
638 // Nested array destructuring with rest property
639 {
640 code: "const data = { vars: ['x','y'], x: 1, y: 2 };\nconst { vars: [x], ...coords } = data;\n console.log(coords)",
641 parserOptions: { ecmaVersion: 2018 },
642 errors: [
643 {
644 line: 2,
645 column: 16,
646 messageId: "unusedVar",
647 data: {
648 varName: "x",
649 action: "assigned a value",
650 additional: ""
651 }
652 }
653 ]
654 },
655
656 // Nested object destructuring with rest property
657 {
658 code: "const data = { defaults: { x: 0 }, x: 1, y: 2 };\nconst { defaults: { x }, ...coords } = data;\n console.log(coords)",
659 parserOptions: { ecmaVersion: 2018 },
660 errors: [
661 {
662 line: 2,
663 column: 21,
664 messageId: "unusedVar",
665 data: {
666 varName: "x",
667 action: "assigned a value",
668 additional: ""
669 }
670 }
671 ]
672 },
673
674 // https://github.com/eslint/eslint/issues/8119
675 {
676 code: "(({a, ...rest}) => {})",
677 options: [{ args: "all", ignoreRestSiblings: true }],
678 parserOptions: { ecmaVersion: 2018 },
679 errors: [definedError("rest")]
680 },
681
682 // https://github.com/eslint/eslint/issues/3714
683 {
684 code: "/* global a$fooz,$foo */\na$fooz;",
685 errors: [
686 {
687 line: 1,
688 column: 18,
689 endLine: 1,
690 endColumn: 22,
691 messageId: "unusedVar",
692 data: {
693 varName: "$foo",
694 action: "defined",
695 additional: ""
696 }
697 }
698 ]
699 },
700 {
701 code: "/* globals a$fooz, $ */\na$fooz;",
702 errors: [
703 {
704 line: 1,
705 column: 20,
706 endLine: 1,
707 endColumn: 21,
708 messageId: "unusedVar",
709 data: {
710 varName: "$",
711 action: "defined",
712 additional: ""
713 }
714 }
715 ]
716 },
717 {
718 code: "/*globals $foo*/",
719 errors: [
720 {
721 line: 1,
722 column: 11,
723 endLine: 1,
724 endColumn: 15,
725 messageId: "unusedVar",
726 data: {
727 varName: "$foo",
728 action: "defined",
729 additional: ""
730 }
731 }
732 ]
733 },
734 {
735 code: "/* global global*/",
736 errors: [
737 {
738 line: 1,
739 column: 11,
740 endLine: 1,
741 endColumn: 17,
742 messageId: "unusedVar",
743 data: {
744 varName: "global",
745 action: "defined",
746 additional: ""
747 }
748 }
749 ]
750 },
751 {
752 code: "/*global foo:true*/",
753 errors: [
754 {
755 line: 1,
756 column: 10,
757 endLine: 1,
758 endColumn: 13,
759 messageId: "unusedVar",
760 data: {
761 varName: "foo",
762 action: "defined",
763 additional: ""
764 }
765 }
766 ]
767 },
768
769 // non ascii.
770 {
771 code: "/*global 変数, 数*/\n変数;",
772 errors: [
773 {
774 line: 1,
775 column: 14,
776 endLine: 1,
777 endColumn: 15,
778 messageId: "unusedVar",
779 data: {
780 varName: "æ•°",
781 action: "defined",
782 additional: ""
783 }
784 }
785 ]
786 },
787
788 // surrogate pair.
789 {
790 code: "/*global 𠮷𩸽, 𠮷*/\n\\u{20BB7}\\u{29E3D};",
791 env: { es6: true },
792 errors: [
793 {
794 line: 1,
795 column: 16,
796 endLine: 1,
797 endColumn: 18,
798 messageId: "unusedVar",
799 data: {
800 varName: "ð ®·",
801 action: "defined",
802 additional: ""
803 }
804 }
805 ]
806 },
807
808 // https://github.com/eslint/eslint/issues/4047
809 {
810 code: "export default function(a) {}",
811 parserOptions: { ecmaVersion: 6, sourceType: "module" },
812 errors: [definedError("a")]
813 },
814 {
815 code: "export default function(a, b) { console.log(a); }",
816 parserOptions: { ecmaVersion: 6, sourceType: "module" },
817 errors: [definedError("b")]
818 },
819 {
820 code: "export default (function(a) {});",
821 parserOptions: { ecmaVersion: 6, sourceType: "module" },
822 errors: [definedError("a")]
823 },
824 {
825 code: "export default (function(a, b) { console.log(a); });",
826 parserOptions: { ecmaVersion: 6, sourceType: "module" },
827 errors: [definedError("b")]
828 },
829 {
830 code: "export default (a) => {};",
831 parserOptions: { ecmaVersion: 6, sourceType: "module" },
832 errors: [definedError("a")]
833 },
834 {
835 code: "export default (a, b) => { console.log(a); };",
836 parserOptions: { ecmaVersion: 6, sourceType: "module" },
837 errors: [definedError("b")]
838 },
839
840 // caughtErrors
841 {
842 code: "try{}catch(err){};",
843 options: [{ caughtErrors: "all" }],
844 errors: [definedError("err")]
845 },
846 {
847 code: "try{}catch(err){};",
848 options: [{ caughtErrors: "all", caughtErrorsIgnorePattern: "^ignore" }],
849 errors: [definedError("err", ". Allowed unused args must match /^ignore/u")]
850 },
851
852 // multiple try catch with one success
853 {
854 code: "try{}catch(ignoreErr){}try{}catch(err){};",
855 options: [{ caughtErrors: "all", caughtErrorsIgnorePattern: "^ignore" }],
856 errors: [definedError("err", ". Allowed unused args must match /^ignore/u")]
857 },
858
859 // multiple try catch both fail
860 {
861 code: "try{}catch(error){}try{}catch(err){};",
862 options: [{ caughtErrors: "all", caughtErrorsIgnorePattern: "^ignore" }],
863 errors: [
864 definedError("error", ". Allowed unused args must match /^ignore/u"),
865 definedError("err", ". Allowed unused args must match /^ignore/u")
866 ]
867 },
868
869 // caughtErrors with other configs
870 {
871 code: "try{}catch(err){};",
872 options: [{ vars: "all", args: "all", caughtErrors: "all" }],
873 errors: [definedError("err")]
874 },
875
876 // no conflict in ignore patterns
877 {
878 code: "try{}catch(err){};",
879 options: [
880 {
881 vars: "all",
882 args: "all",
883 caughtErrors: "all",
884 argsIgnorePattern: "^er"
885 }
886 ],
887 errors: [definedError("err")]
888 },
889
890 // Ignore reads for modifications to itself: https://github.com/eslint/eslint/issues/6348
891 { code: "var a = 0; a = a + 1;", errors: [assignedError("a")] },
892 { code: "var a = 0; a = a + a;", errors: [assignedError("a")] },
893 { code: "var a = 0; a += a + 1;", errors: [assignedError("a")] },
894 { code: "var a = 0; a++;", errors: [assignedError("a")] },
895 { code: "function foo(a) { a = a + 1 } foo();", errors: [assignedError("a")] },
896 { code: "function foo(a) { a += a + 1 } foo();", errors: [assignedError("a")] },
897 { code: "function foo(a) { a++ } foo();", errors: [assignedError("a")] },
898 { code: "var a = 3; a = a * 5 + 6;", errors: [assignedError("a")] },
899 { code: "var a = 2, b = 4; a = a * 2 + b;", errors: [assignedError("a")] },
900
901 // https://github.com/eslint/eslint/issues/6576 (For coverage)
902 {
903 code: "function foo(cb) { cb = function(a) { cb(1 + a); }; bar(not_cb); } foo();",
904 errors: [assignedError("cb")]
905 },
906 {
907 code: "function foo(cb) { cb = function(a) { return cb(1 + a); }(); } foo();",
908 errors: [assignedError("cb")]
909 },
910 {
911 code: "function foo(cb) { cb = (function(a) { cb(1 + a); }, cb); } foo();",
912 errors: [assignedError("cb")]
913 },
914 {
915 code: "function foo(cb) { cb = (0, function(a) { cb(1 + a); }); } foo();",
916 errors: [assignedError("cb")]
917 },
918
919 // https://github.com/eslint/eslint/issues/6646
920 {
921 code: [
922 "while (a) {",
923 " function foo(b) {",
924 " b = b + 1;",
925 " }",
926 " foo()",
927 "}"
928 ].join("\n"),
929 errors: [assignedError("b")]
930 },
931
932 // https://github.com/eslint/eslint/issues/7124
933 {
934 code: "(function(a, b, c) {})",
935 options: [{ argsIgnorePattern: "c" }],
936 errors: [
937 definedError("a", ". Allowed unused args must match /c/u"),
938 definedError("b", ". Allowed unused args must match /c/u")
939 ]
940 },
941 {
942 code: "(function(a, b, {c, d}) {})",
943 options: [{ argsIgnorePattern: "[cd]" }],
944 parserOptions: { ecmaVersion: 6 },
945 errors: [
946 definedError("a", ". Allowed unused args must match /[cd]/u"),
947 definedError("b", ". Allowed unused args must match /[cd]/u")
948 ]
949 },
950 {
951 code: "(function(a, b, {c, d}) {})",
952 options: [{ argsIgnorePattern: "c" }],
953 parserOptions: { ecmaVersion: 6 },
954 errors: [
955 definedError("a", ". Allowed unused args must match /c/u"),
956 definedError("b", ". Allowed unused args must match /c/u"),
957 definedError("d", ". Allowed unused args must match /c/u")
958 ]
959 },
960 {
961 code: "(function(a, b, {c, d}) {})",
962 options: [{ argsIgnorePattern: "d" }],
963 parserOptions: { ecmaVersion: 6 },
964 errors: [
965 definedError("a", ". Allowed unused args must match /d/u"),
966 definedError("b", ". Allowed unused args must match /d/u"),
967 definedError("c", ". Allowed unused args must match /d/u")
968 ]
969 },
970 {
971 code: "/*global\rfoo*/",
972 errors: [{
973 line: 2,
974 column: 1,
975 endLine: 2,
976 endColumn: 4,
977 messageId: "unusedVar",
978 data: {
979 varName: "foo",
980 action: "defined",
981 additional: ""
982 }
983 }]
984 },
985
986 // https://github.com/eslint/eslint/issues/8442
987 {
988 code: "(function ({ a }, b ) { return b; })();",
989 parserOptions: { ecmaVersion: 2015 },
990 errors: [
991 definedError("a")
992 ]
993 },
994 {
995 code: "(function ({ a }, { b, c } ) { return b; })();",
996 parserOptions: { ecmaVersion: 2015 },
997 errors: [
998 definedError("a"),
999 definedError("c")
1000 ]
1001 },
1002
1003 // https://github.com/eslint/eslint/issues/14325
1004 {
1005 code: `let x = 0;
1006 x++, x = 0;`,
1007 parserOptions: { ecmaVersion: 2015 },
1008 errors: [{ ...assignedError("x"), line: 2, column: 18 }]
1009 },
1010 {
1011 code: `let x = 0;
1012 x++, x = 0;
1013 x=3;`,
1014 parserOptions: { ecmaVersion: 2015 },
1015 errors: [{ ...assignedError("x"), line: 3, column: 13 }]
1016 },
1017 {
1018 code: "let x = 0; x++, 0;",
1019 parserOptions: { ecmaVersion: 2015 },
1020 errors: [{ ...assignedError("x"), line: 1, column: 12 }]
1021 },
1022 {
1023 code: "let x = 0; 0, x++;",
1024 parserOptions: { ecmaVersion: 2015 },
1025 errors: [{ ...assignedError("x"), line: 1, column: 15 }]
1026 },
1027 {
1028 code: "let x = 0; 0, (1, x++);",
1029 parserOptions: { ecmaVersion: 2015 },
1030 errors: [{ ...assignedError("x"), line: 1, column: 19 }]
1031 },
1032 {
1033 code: "let x = 0; foo = (x++, 0);",
1034 parserOptions: { ecmaVersion: 2015 },
1035 errors: [{ ...assignedError("x"), line: 1, column: 19 }]
1036 },
1037 {
1038 code: "let x = 0; foo = ((0, x++), 0);",
1039 parserOptions: { ecmaVersion: 2015 },
1040 errors: [{ ...assignedError("x"), line: 1, column: 23 }]
1041 },
1042 {
1043 code: "let x = 0; x += 1, 0;",
1044 parserOptions: { ecmaVersion: 2015 },
1045 errors: [{ ...assignedError("x"), line: 1, column: 12 }]
1046 },
1047 {
1048 code: "let x = 0; 0, x += 1;",
1049 parserOptions: { ecmaVersion: 2015 },
1050 errors: [{ ...assignedError("x"), line: 1, column: 15 }]
1051 },
1052 {
1053 code: "let x = 0; 0, (1, x += 1);",
1054 parserOptions: { ecmaVersion: 2015 },
1055 errors: [{ ...assignedError("x"), line: 1, column: 19 }]
1056 },
1057 {
1058 code: "let x = 0; foo = (x += 1, 0);",
1059 parserOptions: { ecmaVersion: 2015 },
1060 errors: [{ ...assignedError("x"), line: 1, column: 19 }]
1061 },
1062 {
1063 code: "let x = 0; foo = ((0, x += 1), 0);",
1064 parserOptions: { ecmaVersion: 2015 },
1065 errors: [{ ...assignedError("x"), line: 1, column: 23 }]
1066 },
1067 {
1068 code: "(function ({ a, b }, { c } ) { return b; })();",
1069 parserOptions: { ecmaVersion: 2015 },
1070 errors: [
1071 definedError("a"),
1072 definedError("c")
1073 ]
1074 },
1075 {
1076 code: "(function ([ a ], b ) { return b; })();",
1077 parserOptions: { ecmaVersion: 2015 },
1078 errors: [
1079 definedError("a")
1080 ]
1081 },
1082 {
1083 code: "(function ([ a ], [ b, c ] ) { return b; })();",
1084 parserOptions: { ecmaVersion: 2015 },
1085 errors: [
1086 definedError("a"),
1087 definedError("c")
1088 ]
1089 },
1090 {
1091 code: "(function ([ a, b ], [ c ] ) { return b; })();",
1092 parserOptions: { ecmaVersion: 2015 },
1093 errors: [
1094 definedError("a"),
1095 definedError("c")
1096 ]
1097 },
1098
1099 // https://github.com/eslint/eslint/issues/9774
1100 {
1101 code: "(function(_a) {})();",
1102 options: [{ args: "all", varsIgnorePattern: "^_" }],
1103 errors: [definedError("_a")]
1104 },
1105 {
1106 code: "(function(_a) {})();",
1107 options: [{ args: "all", caughtErrorsIgnorePattern: "^_" }],
1108 errors: [definedError("_a")]
1109 },
1110
1111 // https://github.com/eslint/eslint/issues/10982
1112 {
1113 code: "var a = function() { a(); };",
1114 errors: [assignedError("a")]
1115 },
1116 {
1117 code: "var a = function(){ return function() { a(); } };",
1118 errors: [assignedError("a")]
1119 },
1120 {
1121 code: "const a = () => { a(); };",
1122 parserOptions: { ecmaVersion: 2015 },
1123 errors: [assignedError("a")]
1124 },
1125 {
1126 code: "const a = () => () => { a(); };",
1127 parserOptions: { ecmaVersion: 2015 },
1128 errors: [assignedError("a")]
1129 },
1130 {
1131 code: `let myArray = [1,2,3,4].filter((x) => x == 0);
1132 myArray = myArray.filter((x) => x == 1);`,
1133 parserOptions: { ecmaVersion: 2015 },
1134 errors: [{ ...assignedError("myArray"), line: 2, column: 5 }]
1135 },
1136 {
1137 code: "const a = 1; a += 1;",
1138 parserOptions: { ecmaVersion: 2015 },
1139 errors: [{ ...assignedError("a"), line: 1, column: 14 }]
1140 },
1141 {
1142 code: "var a = function() { a(); };",
1143 errors: [{ ...assignedError("a"), line: 1, column: 5 }]
1144 },
1145 {
1146 code: "var a = function(){ return function() { a(); } };",
1147 errors: [{ ...assignedError("a"), line: 1, column: 5 }]
1148 },
1149 {
1150 code: "const a = () => { a(); };",
1151 parserOptions: { ecmaVersion: 2015 },
1152 errors: [{ ...assignedError("a"), line: 1, column: 7 }]
1153 },
1154 {
1155 code: "const a = () => () => { a(); };",
1156 parserOptions: { ecmaVersion: 2015 },
1157 errors: [{ ...assignedError("a"), line: 1, column: 7 }]
1158 },
1159
1160 // https://github.com/eslint/eslint/issues/14324
1161 {
1162 code: "let x = [];\nx = x.concat(x);",
1163 parserOptions: { ecmaVersion: 2015 },
1164 errors: [{ ...assignedError("x"), line: 2, column: 1 }]
1165 },
1166 {
1167
1168 code: `let a = 'a';
1169 a = 10;
1170 function foo(){
1171 a = 11;
1172 a = () => {
1173 a = 13
1174 }
1175 }`,
1176 parserOptions: { ecmaVersion: 2020 },
1177 errors: [{ ...assignedError("a"), line: 2, column: 13 }, { ...definedError("foo"), line: 3, column: 22 }]
1178 },
1179 {
1180 code: `let foo;
1181 init();
1182 foo = foo + 2;
1183 function init() {
1184 foo = 1;
1185 }`,
1186 parserOptions: { ecmaVersion: 2020 },
1187 errors: [{ ...assignedError("foo"), line: 3, column: 13 }]
1188 },
1189 {
1190 code: `function foo(n) {
1191 if (n < 2) return 1;
1192 return n * foo(n - 1);
1193 }`,
1194 parserOptions: { ecmaVersion: 2020 },
1195 errors: [{ ...definedError("foo"), line: 1, column: 10 }]
1196 },
1197 {
1198 code: `let c = 'c'
1199 c = 10
1200 function foo1() {
1201 c = 11
1202 c = () => {
1203 c = 13
1204 }
1205 }
1206
1207 c = foo1`,
1208 parserOptions: { ecmaVersion: 2020 },
1209 errors: [{ ...assignedError("c"), line: 10, column: 1 }]
1210 }
1211 ]
1212 });