]>
Commit | Line | Data |
---|---|---|
eb39fafa DC |
1 | /** |
2 | * @fileoverview Prefer destructuring from arrays and objects | |
3 | * @author Alex LaFroscia | |
4 | */ | |
5 | "use strict"; | |
6 | ||
7 | //------------------------------------------------------------------------------ | |
8 | // Requirements | |
9 | //------------------------------------------------------------------------------ | |
10 | ||
11 | const rule = require("../../../lib/rules/prefer-destructuring"), | |
12 | { RuleTester } = require("../../../lib/rule-tester"); | |
13 | ||
14 | ||
15 | //------------------------------------------------------------------------------ | |
16 | // Tests | |
17 | //------------------------------------------------------------------------------ | |
18 | ||
609c276f | 19 | const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 2022 } }); |
eb39fafa DC |
20 | |
21 | ruleTester.run("prefer-destructuring", rule, { | |
22 | valid: [ | |
23 | "var [foo] = array;", | |
24 | "var { foo } = object;", | |
25 | "var foo;", | |
26 | { | |
27 | ||
28 | // Ensure that the default behavior does not require destructuring when renaming | |
29 | code: "var foo = object.bar;", | |
30 | options: [{ VariableDeclarator: { object: true } }] | |
31 | }, | |
32 | { | |
33 | ||
34 | // Ensure that the default behavior does not require destructuring when renaming | |
35 | code: "var foo = object.bar;", | |
36 | options: [{ object: true }] | |
37 | }, | |
38 | { | |
39 | code: "var foo = object.bar;", | |
40 | options: [{ VariableDeclarator: { object: true } }, { enforceForRenamedProperties: false }] | |
41 | }, | |
42 | { | |
43 | code: "var foo = object.bar;", | |
44 | options: [{ object: true }, { enforceForRenamedProperties: false }] | |
45 | }, | |
46 | { | |
47 | code: "var foo = object['bar'];", | |
48 | options: [{ VariableDeclarator: { object: true } }, { enforceForRenamedProperties: false }] | |
49 | }, | |
50 | { | |
51 | code: "var foo = object[bar];", | |
52 | options: [{ object: true }, { enforceForRenamedProperties: false }] | |
53 | }, | |
54 | { | |
55 | code: "var { bar: foo } = object;", | |
56 | options: [{ VariableDeclarator: { object: true } }, { enforceForRenamedProperties: true }] | |
57 | }, | |
58 | { | |
59 | code: "var { bar: foo } = object;", | |
60 | options: [{ object: true }, { enforceForRenamedProperties: true }] | |
61 | }, | |
62 | { | |
63 | code: "var { [bar]: foo } = object;", | |
64 | options: [{ VariableDeclarator: { object: true } }, { enforceForRenamedProperties: true }] | |
65 | }, | |
66 | { | |
67 | code: "var { [bar]: foo } = object;", | |
68 | options: [{ object: true }, { enforceForRenamedProperties: true }] | |
69 | }, | |
70 | { | |
71 | code: "var foo = array[0];", | |
72 | options: [{ VariableDeclarator: { array: false } }] | |
73 | }, | |
74 | { | |
75 | code: "var foo = array[0];", | |
76 | options: [{ array: false }] | |
77 | }, | |
78 | { | |
79 | code: "var foo = object.foo;", | |
80 | options: [{ VariableDeclarator: { object: false } }] | |
81 | }, | |
82 | { | |
83 | code: "var foo = object['foo'];", | |
84 | options: [{ VariableDeclarator: { object: false } }] | |
85 | }, | |
86 | "({ foo } = object);", | |
87 | { | |
88 | ||
89 | // Fix #8654 | |
90 | code: "var foo = array[0];", | |
91 | options: [{ VariableDeclarator: { array: false } }, { enforceForRenamedProperties: true }] | |
92 | }, | |
93 | { | |
94 | ||
95 | // Fix #8654 | |
96 | code: "var foo = array[0];", | |
97 | options: [{ array: false }, { enforceForRenamedProperties: true }] | |
98 | }, | |
99 | "[foo] = array;", | |
100 | "foo += array[0]", | |
6f036462 TL |
101 | { |
102 | code: "foo &&= array[0]", | |
103 | parserOptions: { ecmaVersion: 2021 } | |
104 | }, | |
eb39fafa | 105 | "foo += bar.foo", |
6f036462 TL |
106 | { |
107 | code: "foo ||= bar.foo", | |
108 | parserOptions: { ecmaVersion: 2021 } | |
109 | }, | |
110 | { | |
111 | code: "foo ??= bar['foo']", | |
112 | parserOptions: { ecmaVersion: 2021 } | |
113 | }, | |
eb39fafa DC |
114 | { |
115 | code: "foo = object.foo;", | |
116 | options: [{ AssignmentExpression: { object: false } }, { enforceForRenamedProperties: true }] | |
117 | }, | |
118 | { | |
119 | code: "foo = object.foo;", | |
120 | options: [{ AssignmentExpression: { object: false } }, { enforceForRenamedProperties: false }] | |
121 | }, | |
122 | { | |
123 | code: "foo = array[0];", | |
124 | options: [{ AssignmentExpression: { array: false } }, { enforceForRenamedProperties: true }] | |
125 | }, | |
126 | { | |
127 | code: "foo = array[0];", | |
128 | options: [{ AssignmentExpression: { array: false } }, { enforceForRenamedProperties: false }] | |
129 | }, | |
130 | { | |
131 | code: "foo = array[0];", | |
132 | options: [{ VariableDeclarator: { array: true }, AssignmentExpression: { array: false } }, { enforceForRenamedProperties: false }] | |
133 | }, | |
134 | { | |
135 | code: "var foo = array[0];", | |
136 | options: [{ VariableDeclarator: { array: false }, AssignmentExpression: { array: true } }, { enforceForRenamedProperties: false }] | |
137 | }, | |
138 | { | |
139 | code: "foo = object.foo;", | |
140 | options: [{ VariableDeclarator: { object: true }, AssignmentExpression: { object: false } }] | |
141 | }, | |
142 | { | |
143 | code: "var foo = object.foo;", | |
144 | options: [{ VariableDeclarator: { object: false }, AssignmentExpression: { object: true } }] | |
145 | }, | |
146 | "class Foo extends Bar { static foo() {var foo = super.foo} }", | |
147 | "foo = bar[foo];", | |
148 | "var foo = bar[foo];", | |
149 | { | |
150 | code: "var {foo: {bar}} = object;", | |
151 | options: [{ object: true }] | |
152 | }, | |
153 | { | |
154 | code: "var {bar} = object.foo;", | |
155 | options: [{ object: true }] | |
6f036462 TL |
156 | }, |
157 | ||
158 | // Optional chaining | |
159 | "var foo = array?.[0];", // because the fixed code can throw TypeError. | |
609c276f TL |
160 | "var foo = object?.foo;", |
161 | ||
162 | // Private identifiers | |
163 | "class C { #x; foo() { const x = this.#x; } }", | |
164 | "class C { #x; foo() { x = this.#x; } }", | |
165 | "class C { #x; foo(a) { x = a.#x; } }", | |
166 | { | |
167 | code: "class C { #x; foo() { const x = this.#x; } }", | |
168 | options: [{ array: true, object: true }, { enforceForRenamedProperties: true }] | |
169 | }, | |
170 | { | |
171 | code: "class C { #x; foo() { const y = this.#x; } }", | |
172 | options: [{ array: true, object: true }, { enforceForRenamedProperties: true }] | |
173 | }, | |
174 | { | |
175 | code: "class C { #x; foo() { x = this.#x; } }", | |
176 | options: [{ array: true, object: true }, { enforceForRenamedProperties: true }] | |
177 | }, | |
178 | { | |
179 | code: "class C { #x; foo() { y = this.#x; } }", | |
180 | options: [{ array: true, object: true }, { enforceForRenamedProperties: true }] | |
181 | }, | |
182 | { | |
183 | code: "class C { #x; foo(a) { x = a.#x; } }", | |
184 | options: [{ array: true, object: true }, { enforceForRenamedProperties: true }] | |
185 | }, | |
186 | { | |
187 | code: "class C { #x; foo(a) { y = a.#x; } }", | |
188 | options: [{ array: true, object: true }, { enforceForRenamedProperties: true }] | |
189 | }, | |
190 | { | |
191 | code: "class C { #x; foo() { x = this.a.#x; } }", | |
192 | options: [{ array: true, object: true }, { enforceForRenamedProperties: true }] | |
193 | } | |
eb39fafa DC |
194 | ], |
195 | ||
196 | invalid: [ | |
197 | { | |
198 | code: "var foo = array[0];", | |
199 | output: null, | |
200 | errors: [{ | |
201 | messageId: "preferDestructuring", | |
202 | data: { type: "array" }, | |
203 | type: "VariableDeclarator" | |
204 | }] | |
205 | }, | |
206 | { | |
207 | code: "foo = array[0];", | |
208 | output: null, | |
209 | errors: [{ | |
210 | messageId: "preferDestructuring", | |
211 | data: { type: "array" }, | |
212 | type: "AssignmentExpression" | |
213 | }] | |
214 | }, | |
215 | { | |
216 | code: "var foo = object.foo;", | |
217 | output: "var {foo} = object;", | |
218 | errors: [{ | |
219 | messageId: "preferDestructuring", | |
220 | data: { type: "object" }, | |
221 | type: "VariableDeclarator" | |
222 | }] | |
223 | }, | |
6f036462 TL |
224 | { |
225 | code: "var foo = (a, b).foo;", | |
226 | output: "var {foo} = (a, b);", | |
227 | errors: [{ | |
228 | messageId: "preferDestructuring", | |
229 | data: { type: "object" }, | |
230 | type: "VariableDeclarator" | |
231 | }] | |
232 | }, | |
233 | { | |
234 | code: "var length = (() => {}).length;", | |
235 | output: "var {length} = () => {};", | |
236 | errors: [{ | |
237 | messageId: "preferDestructuring", | |
238 | data: { type: "object" }, | |
239 | type: "VariableDeclarator" | |
240 | }] | |
241 | }, | |
242 | { | |
243 | code: "var foo = (a = b).foo;", | |
244 | output: "var {foo} = a = b;", | |
245 | errors: [{ | |
246 | messageId: "preferDestructuring", | |
247 | data: { type: "object" }, | |
248 | type: "VariableDeclarator" | |
249 | }] | |
250 | }, | |
251 | { | |
252 | code: "var foo = (a || b).foo;", | |
253 | output: "var {foo} = a || b;", | |
254 | errors: [{ | |
255 | messageId: "preferDestructuring", | |
256 | data: { type: "object" }, | |
257 | type: "VariableDeclarator" | |
258 | }] | |
259 | }, | |
260 | { | |
261 | code: "var foo = (f()).foo;", | |
262 | output: "var {foo} = f();", | |
263 | errors: [{ | |
264 | messageId: "preferDestructuring", | |
265 | data: { type: "object" }, | |
266 | type: "VariableDeclarator" | |
267 | }] | |
268 | }, | |
eb39fafa DC |
269 | { |
270 | code: "var foo = object.bar.foo;", | |
271 | output: "var {foo} = object.bar;", | |
272 | errors: [{ | |
273 | messageId: "preferDestructuring", | |
274 | data: { type: "object" }, | |
275 | type: "VariableDeclarator" | |
276 | }] | |
277 | }, | |
278 | { | |
279 | code: "var foobar = object.bar;", | |
280 | output: null, | |
281 | options: [{ VariableDeclarator: { object: true } }, { enforceForRenamedProperties: true }], | |
282 | errors: [{ | |
283 | messageId: "preferDestructuring", | |
284 | data: { type: "object" }, | |
285 | type: "VariableDeclarator" | |
286 | }] | |
287 | }, | |
288 | { | |
289 | code: "var foobar = object.bar;", | |
290 | output: null, | |
291 | options: [{ object: true }, { enforceForRenamedProperties: true }], | |
292 | errors: [{ | |
293 | messageId: "preferDestructuring", | |
294 | data: { type: "object" }, | |
295 | type: "VariableDeclarator" | |
296 | }] | |
297 | }, | |
298 | { | |
299 | code: "var foo = object[bar];", | |
300 | output: null, | |
301 | options: [{ VariableDeclarator: { object: true } }, { enforceForRenamedProperties: true }], | |
302 | errors: [{ | |
303 | messageId: "preferDestructuring", | |
304 | data: { type: "object" }, | |
305 | type: "VariableDeclarator" | |
306 | }] | |
307 | }, | |
308 | { | |
309 | code: "var foo = object[bar];", | |
310 | output: null, | |
311 | options: [{ object: true }, { enforceForRenamedProperties: true }], | |
312 | errors: [{ | |
313 | messageId: "preferDestructuring", | |
314 | data: { type: "object" }, | |
315 | type: "VariableDeclarator" | |
316 | }] | |
317 | }, | |
6f036462 TL |
318 | { |
319 | code: "var foo = object[foo];", | |
320 | output: null, | |
321 | options: [{ object: true }, { enforceForRenamedProperties: true }], | |
322 | errors: [{ | |
323 | messageId: "preferDestructuring", | |
324 | data: { type: "object" }, | |
325 | type: "VariableDeclarator" | |
326 | }] | |
327 | }, | |
eb39fafa DC |
328 | { |
329 | code: "var foo = object['foo'];", | |
330 | output: null, | |
331 | errors: [{ | |
332 | messageId: "preferDestructuring", | |
333 | data: { type: "object" }, | |
334 | type: "VariableDeclarator" | |
335 | }] | |
336 | }, | |
337 | { | |
338 | code: "foo = object.foo;", | |
339 | output: null, | |
340 | errors: [{ | |
341 | messageId: "preferDestructuring", | |
342 | data: { type: "object" }, | |
343 | type: "AssignmentExpression" | |
344 | }] | |
345 | }, | |
346 | { | |
347 | code: "foo = object['foo'];", | |
348 | output: null, | |
349 | errors: [{ | |
350 | messageId: "preferDestructuring", | |
351 | data: { type: "object" }, | |
352 | type: "AssignmentExpression" | |
353 | }] | |
354 | }, | |
355 | { | |
356 | code: "var foo = array[0];", | |
357 | output: null, | |
358 | options: [{ VariableDeclarator: { array: true } }, { enforceForRenamedProperties: true }], | |
359 | errors: [{ | |
360 | messageId: "preferDestructuring", | |
361 | data: { type: "array" }, | |
362 | type: "VariableDeclarator" | |
363 | }] | |
364 | }, | |
365 | { | |
366 | code: "foo = array[0];", | |
367 | output: null, | |
368 | options: [{ AssignmentExpression: { array: true } }], | |
369 | errors: [{ | |
370 | messageId: "preferDestructuring", | |
371 | data: { type: "array" }, | |
372 | type: "AssignmentExpression" | |
373 | }] | |
374 | }, | |
375 | { | |
376 | code: "var foo = array[0];", | |
377 | output: null, | |
378 | options: [ | |
379 | { | |
380 | VariableDeclarator: { array: true }, | |
381 | AssignmentExpression: { array: false } | |
382 | }, | |
383 | { enforceForRenamedProperties: true } | |
384 | ], | |
385 | errors: [{ | |
386 | messageId: "preferDestructuring", | |
387 | data: { type: "array" }, | |
388 | type: "VariableDeclarator" | |
389 | }] | |
390 | }, | |
391 | { | |
392 | code: "var foo = array[0];", | |
393 | output: null, | |
394 | options: [ | |
395 | { | |
396 | VariableDeclarator: { array: true }, | |
397 | AssignmentExpression: { array: false } | |
398 | } | |
399 | ], | |
400 | errors: [{ | |
401 | messageId: "preferDestructuring", | |
402 | data: { type: "array" }, | |
403 | type: "VariableDeclarator" | |
404 | }] | |
405 | }, | |
406 | { | |
407 | code: "foo = array[0];", | |
408 | output: null, | |
409 | options: [ | |
410 | { | |
411 | VariableDeclarator: { array: false }, | |
412 | AssignmentExpression: { array: true } | |
413 | } | |
414 | ], | |
415 | errors: [{ | |
416 | messageId: "preferDestructuring", | |
417 | data: { type: "array" }, | |
418 | type: "AssignmentExpression" | |
419 | }] | |
420 | }, | |
421 | { | |
422 | code: "foo = object.foo;", | |
423 | output: null, | |
424 | options: [ | |
425 | { | |
426 | VariableDeclarator: { array: true, object: false }, | |
427 | AssignmentExpression: { object: true } | |
428 | } | |
429 | ], | |
430 | errors: [{ | |
431 | messageId: "preferDestructuring", | |
432 | data: { type: "object" }, | |
433 | type: "AssignmentExpression" | |
434 | }] | |
435 | }, | |
436 | { | |
437 | code: "class Foo extends Bar { static foo() {var bar = super.foo.bar} }", | |
438 | output: "class Foo extends Bar { static foo() {var {bar} = super.foo} }", | |
439 | errors: [{ | |
440 | messageId: "preferDestructuring", | |
441 | data: { type: "object" }, | |
442 | type: "VariableDeclarator" | |
443 | }] | |
6f036462 TL |
444 | }, |
445 | ||
446 | // comments | |
447 | { | |
448 | code: "var /* comment */ foo = object.foo;", | |
449 | output: "var /* comment */ {foo} = object;", | |
450 | errors: [{ | |
451 | messageId: "preferDestructuring", | |
452 | data: { type: "object" }, | |
453 | type: "VariableDeclarator" | |
454 | }] | |
455 | }, | |
456 | { | |
457 | code: "var a, /* comment */foo = object.foo;", | |
458 | output: "var a, /* comment */{foo} = object;", | |
459 | errors: [{ | |
460 | messageId: "preferDestructuring", | |
461 | data: { type: "object" }, | |
462 | type: "VariableDeclarator" | |
463 | }] | |
464 | }, | |
465 | { | |
466 | code: "var foo /* comment */ = object.foo;", | |
467 | output: null, | |
468 | errors: [{ | |
469 | messageId: "preferDestructuring", | |
470 | data: { type: "object" }, | |
471 | type: "VariableDeclarator" | |
472 | }] | |
473 | }, | |
474 | { | |
475 | code: "var a, foo /* comment */ = object.foo;", | |
476 | output: null, | |
477 | errors: [{ | |
478 | messageId: "preferDestructuring", | |
479 | data: { type: "object" }, | |
480 | type: "VariableDeclarator" | |
481 | }] | |
482 | }, | |
483 | { | |
484 | code: "var foo /* comment */ = object.foo, a;", | |
485 | output: null, | |
486 | errors: [{ | |
487 | messageId: "preferDestructuring", | |
488 | data: { type: "object" }, | |
489 | type: "VariableDeclarator" | |
490 | }] | |
491 | }, | |
492 | { | |
493 | code: "var foo // comment\n = object.foo;", | |
494 | output: null, | |
495 | errors: [{ | |
496 | messageId: "preferDestructuring", | |
497 | data: { type: "object" }, | |
498 | type: "VariableDeclarator" | |
499 | }] | |
500 | }, | |
501 | { | |
502 | code: "var foo = /* comment */ object.foo;", | |
503 | output: null, | |
504 | errors: [{ | |
505 | messageId: "preferDestructuring", | |
506 | data: { type: "object" }, | |
507 | type: "VariableDeclarator" | |
508 | }] | |
509 | }, | |
510 | { | |
511 | code: "var foo = // comment\n object.foo;", | |
512 | output: null, | |
513 | errors: [{ | |
514 | messageId: "preferDestructuring", | |
515 | data: { type: "object" }, | |
516 | type: "VariableDeclarator" | |
517 | }] | |
518 | }, | |
519 | { | |
520 | code: "var foo = (/* comment */ object).foo;", | |
521 | output: null, | |
522 | errors: [{ | |
523 | messageId: "preferDestructuring", | |
524 | data: { type: "object" }, | |
525 | type: "VariableDeclarator" | |
526 | }] | |
527 | }, | |
528 | { | |
529 | code: "var foo = (object /* comment */).foo;", | |
530 | output: null, | |
531 | errors: [{ | |
532 | messageId: "preferDestructuring", | |
533 | data: { type: "object" }, | |
534 | type: "VariableDeclarator" | |
535 | }] | |
536 | }, | |
537 | { | |
538 | code: "var foo = bar(/* comment */).foo;", | |
539 | output: "var {foo} = bar(/* comment */);", | |
540 | errors: [{ | |
541 | messageId: "preferDestructuring", | |
542 | data: { type: "object" }, | |
543 | type: "VariableDeclarator" | |
544 | }] | |
545 | }, | |
546 | { | |
547 | code: "var foo = bar/* comment */.baz.foo;", | |
548 | output: "var {foo} = bar/* comment */.baz;", | |
549 | errors: [{ | |
550 | messageId: "preferDestructuring", | |
551 | data: { type: "object" }, | |
552 | type: "VariableDeclarator" | |
553 | }] | |
554 | }, | |
555 | { | |
556 | code: "var foo = bar[// comment\nbaz].foo;", | |
557 | output: "var {foo} = bar[// comment\nbaz];", | |
558 | errors: [{ | |
559 | messageId: "preferDestructuring", | |
560 | data: { type: "object" }, | |
561 | type: "VariableDeclarator" | |
562 | }] | |
563 | }, | |
564 | { | |
565 | code: "var foo // comment\n = bar(/* comment */).foo;", | |
566 | output: null, | |
567 | errors: [{ | |
568 | messageId: "preferDestructuring", | |
569 | data: { type: "object" }, | |
570 | type: "VariableDeclarator" | |
571 | }] | |
572 | }, | |
573 | { | |
574 | code: "var foo = bar/* comment */.baz/* comment */.foo;", | |
575 | output: null, | |
576 | errors: [{ | |
577 | messageId: "preferDestructuring", | |
578 | data: { type: "object" }, | |
579 | type: "VariableDeclarator" | |
580 | }] | |
581 | }, | |
582 | { | |
583 | code: "var foo = object// comment\n.foo;", | |
584 | output: null, | |
585 | errors: [{ | |
586 | messageId: "preferDestructuring", | |
587 | data: { type: "object" }, | |
588 | type: "VariableDeclarator" | |
589 | }] | |
590 | }, | |
591 | { | |
592 | code: "var foo = object./* comment */foo;", | |
593 | output: null, | |
594 | errors: [{ | |
595 | messageId: "preferDestructuring", | |
596 | data: { type: "object" }, | |
597 | type: "VariableDeclarator" | |
598 | }] | |
599 | }, | |
600 | { | |
601 | code: "var foo = (/* comment */ object.foo);", | |
602 | output: null, | |
603 | errors: [{ | |
604 | messageId: "preferDestructuring", | |
605 | data: { type: "object" }, | |
606 | type: "VariableDeclarator" | |
607 | }] | |
608 | }, | |
609 | { | |
610 | code: "var foo = (object.foo /* comment */);", | |
611 | output: null, | |
612 | errors: [{ | |
613 | messageId: "preferDestructuring", | |
614 | data: { type: "object" }, | |
615 | type: "VariableDeclarator" | |
616 | }] | |
617 | }, | |
618 | { | |
619 | code: "var foo = object.foo/* comment */;", | |
620 | output: "var {foo} = object/* comment */;", | |
621 | errors: [{ | |
622 | messageId: "preferDestructuring", | |
623 | data: { type: "object" }, | |
624 | type: "VariableDeclarator" | |
625 | }] | |
626 | }, | |
627 | { | |
628 | code: "var foo = object.foo// comment", | |
629 | output: "var {foo} = object// comment", | |
630 | errors: [{ | |
631 | messageId: "preferDestructuring", | |
632 | data: { type: "object" }, | |
633 | type: "VariableDeclarator" | |
634 | }] | |
635 | }, | |
636 | { | |
637 | code: "var foo = object.foo/* comment */, a;", | |
638 | output: "var {foo} = object/* comment */, a;", | |
639 | errors: [{ | |
640 | messageId: "preferDestructuring", | |
641 | data: { type: "object" }, | |
642 | type: "VariableDeclarator" | |
643 | }] | |
644 | }, | |
645 | { | |
646 | code: "var foo = object.foo// comment\n, a;", | |
647 | output: "var {foo} = object// comment\n, a;", | |
648 | errors: [{ | |
649 | messageId: "preferDestructuring", | |
650 | data: { type: "object" }, | |
651 | type: "VariableDeclarator" | |
652 | }] | |
653 | }, | |
654 | { | |
655 | code: "var foo = object.foo, /* comment */ a;", | |
656 | output: "var {foo} = object, /* comment */ a;", | |
657 | errors: [{ | |
658 | messageId: "preferDestructuring", | |
659 | data: { type: "object" }, | |
660 | type: "VariableDeclarator" | |
661 | }] | |
eb39fafa DC |
662 | } |
663 | ] | |
664 | }); |