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