eslint-plugin-ts-data-forge 0.10.5 → 0.10.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. package/README.md +3 -3
  2. package/dist/plugin.d.mts +2 -2
  3. package/dist/plugin.d.mts.map +1 -1
  4. package/dist/plugin.mjs +1 -0
  5. package/dist/plugin.mjs.map +1 -1
  6. package/dist/rule-types.d.mts +5 -5
  7. package/dist/rules/ast-utils.d.mts +8 -9
  8. package/dist/rules/ast-utils.d.mts.map +1 -1
  9. package/dist/rules/ast-utils.mjs +3 -4
  10. package/dist/rules/ast-utils.mjs.map +1 -1
  11. package/dist/rules/import-binding.d.mts +38 -0
  12. package/dist/rules/import-binding.d.mts.map +1 -0
  13. package/dist/rules/import-binding.mjs +53 -0
  14. package/dist/rules/import-binding.mjs.map +1 -0
  15. package/dist/rules/mutable-result.mjs +37 -37
  16. package/dist/rules/mutable-result.mjs.map +1 -1
  17. package/dist/rules/no-unnecessary-type-guard.d.mts.map +1 -1
  18. package/dist/rules/no-unnecessary-type-guard.mjs +146 -143
  19. package/dist/rules/no-unnecessary-type-guard.mjs.map +1 -1
  20. package/dist/rules/prefer-arr-generate.d.mts +2 -2
  21. package/dist/rules/prefer-arr-generate.d.mts.map +1 -1
  22. package/dist/rules/prefer-arr-generate.mjs +146 -136
  23. package/dist/rules/prefer-arr-generate.mjs.map +1 -1
  24. package/dist/rules/prefer-arr-is-bounded-length-array.d.mts.map +1 -1
  25. package/dist/rules/prefer-arr-is-bounded-length-array.mjs +14 -16
  26. package/dist/rules/prefer-arr-is-bounded-length-array.mjs.map +1 -1
  27. package/dist/rules/prefer-arr-is-fixed-length-array.d.mts.map +1 -1
  28. package/dist/rules/prefer-arr-is-fixed-length-array.mjs +15 -17
  29. package/dist/rules/prefer-arr-is-fixed-length-array.mjs.map +1 -1
  30. package/dist/rules/prefer-arr-is-max-length-array.d.mts.map +1 -1
  31. package/dist/rules/prefer-arr-is-max-length-array.mjs +14 -16
  32. package/dist/rules/prefer-arr-is-max-length-array.mjs.map +1 -1
  33. package/dist/rules/prefer-arr-is-min-length-array.d.mts.map +1 -1
  34. package/dist/rules/prefer-arr-is-min-length-array.mjs +14 -16
  35. package/dist/rules/prefer-arr-is-min-length-array.mjs.map +1 -1
  36. package/dist/rules/prefer-arr-is-non-empty.d.mts.map +1 -1
  37. package/dist/rules/prefer-arr-is-non-empty.mjs +14 -16
  38. package/dist/rules/prefer-arr-is-non-empty.mjs.map +1 -1
  39. package/dist/rules/prefer-arr-scan.d.mts.map +1 -1
  40. package/dist/rules/prefer-arr-scan.mjs +9 -18
  41. package/dist/rules/prefer-arr-scan.mjs.map +1 -1
  42. package/dist/rules/prefer-arr-sum.d.mts.map +1 -1
  43. package/dist/rules/prefer-arr-sum.mjs +16 -21
  44. package/dist/rules/prefer-arr-sum.mjs.map +1 -1
  45. package/dist/rules/prefer-arr-uniq.d.mts.map +1 -1
  46. package/dist/rules/prefer-arr-uniq.mjs +38 -43
  47. package/dist/rules/prefer-arr-uniq.mjs.map +1 -1
  48. package/dist/rules/prefer-as-int.d.mts.map +1 -1
  49. package/dist/rules/prefer-as-int.mjs +19 -26
  50. package/dist/rules/prefer-as-int.mjs.map +1 -1
  51. package/dist/rules/prefer-canonical-array-slicing.d.mts.map +1 -1
  52. package/dist/rules/prefer-canonical-array-slicing.mjs +49 -16
  53. package/dist/rules/prefer-canonical-array-slicing.mjs.map +1 -1
  54. package/dist/rules/prefer-canonical-length-cast.mjs +15 -15
  55. package/dist/rules/prefer-canonical-length-cast.mjs.map +1 -1
  56. package/dist/rules/prefer-num-safe-parse-float.d.mts +1 -1
  57. package/dist/rules/prefer-num-safe-parse-float.d.mts.map +1 -1
  58. package/dist/rules/prefer-num-safe-parse-int.d.mts +1 -1
  59. package/dist/rules/prefer-num-safe-parse-int.d.mts.map +1 -1
  60. package/dist/rules/prefer-obj-over-entries-round-trip.d.mts.map +1 -1
  61. package/dist/rules/prefer-obj-over-entries-round-trip.mjs +100 -99
  62. package/dist/rules/prefer-obj-over-entries-round-trip.mjs.map +1 -1
  63. package/dist/rules/prefer-pipe-map-nullable.d.mts +2 -2
  64. package/dist/rules/prefer-pipe-map-nullable.d.mts.map +1 -1
  65. package/dist/rules/prefer-pipe-map-nullable.mjs +2 -4
  66. package/dist/rules/prefer-pipe-map-nullable.mjs.map +1 -1
  67. package/dist/rules/prefer-range-for-loop.d.mts.map +1 -1
  68. package/dist/rules/prefer-range-for-loop.mjs +18 -24
  69. package/dist/rules/prefer-range-for-loop.mjs.map +1 -1
  70. package/dist/rules/rules.d.mts +2 -2
  71. package/package.json +6 -6
  72. package/src/plugin.mts +4 -3
  73. package/src/rule-types.mts +5 -5
  74. package/src/rules/ast-utils.mts +14 -15
  75. package/src/rules/import-binding.mts +94 -0
  76. package/src/rules/mutable-result.mts +56 -56
  77. package/src/rules/no-unnecessary-type-guard.mts +203 -207
  78. package/src/rules/no-unnecessary-type-guard.test.mts +62 -2
  79. package/src/rules/prefer-arr-generate.mts +222 -214
  80. package/src/rules/prefer-arr-generate.test.mts +490 -133
  81. package/src/rules/prefer-arr-is-bounded-length-array.mts +22 -33
  82. package/src/rules/prefer-arr-is-fixed-length-array.mts +26 -38
  83. package/src/rules/prefer-arr-is-fixed-length-array.test.mts +16 -7
  84. package/src/rules/prefer-arr-is-max-length-array.mts +23 -36
  85. package/src/rules/prefer-arr-is-max-length-array.test.mts +16 -7
  86. package/src/rules/prefer-arr-is-min-length-array.mts +23 -36
  87. package/src/rules/prefer-arr-is-min-length-array.test.mts +16 -7
  88. package/src/rules/prefer-arr-is-non-empty.mts +17 -34
  89. package/src/rules/prefer-arr-is-non-empty.test.mts +110 -0
  90. package/src/rules/prefer-arr-scan.mts +17 -42
  91. package/src/rules/prefer-arr-scan.test.mts +55 -0
  92. package/src/rules/prefer-arr-sum.mts +22 -36
  93. package/src/rules/prefer-arr-uniq.mts +51 -62
  94. package/src/rules/prefer-arr-uniq.test.mts +46 -20
  95. package/src/rules/prefer-as-int.mts +27 -52
  96. package/src/rules/prefer-as-int.test.mts +79 -29
  97. package/src/rules/prefer-canonical-array-slicing.mts +101 -40
  98. package/src/rules/prefer-canonical-array-slicing.test.mts +133 -34
  99. package/src/rules/prefer-canonical-length-cast.mts +29 -29
  100. package/src/rules/prefer-canonical-length-guard.mts +2 -2
  101. package/src/rules/prefer-num-safe-parse-float.test.mts +255 -94
  102. package/src/rules/prefer-num-safe-parse-int.test.mts +212 -76
  103. package/src/rules/prefer-obj-over-entries-round-trip.mts +152 -170
  104. package/src/rules/prefer-obj-over-entries-round-trip.test.mts +48 -6
  105. package/src/rules/prefer-pipe-map-nullable.mts +17 -19
  106. package/src/rules/prefer-range-for-loop.mts +37 -61
  107. package/src/rules/prefer-range-for-loop.test.mts +2 -2
@@ -202,25 +202,40 @@ describe('prefer-arr-generate', () => {
202
202
  const ys = xs.flatMap((x) => (x === undefined ? [] : [x]));
203
203
  const zs = xs.flatMap((x) => (skip ? [] : [x]));
204
204
  `,
205
- output: dedent`
206
- import { Arr } from 'ts-data-forge';
207
- declare const xs: readonly (number | undefined)[];
208
- declare const skip: boolean;
209
- const ys = Arr.generate(function* () {
210
- for (const x of xs) {
211
- if (x !== undefined) {
212
- yield x;
205
+ output: [
206
+ dedent`
207
+ import { Arr } from 'ts-data-forge';
208
+ declare const xs: readonly (number | undefined)[];
209
+ declare const skip: boolean;
210
+ const ys = Arr.generate(function* () {
211
+ for (const x of xs) {
212
+ if (x !== undefined) {
213
+ yield x;
214
+ }
213
215
  }
214
- }
215
- });
216
- const zs = Arr.generate(function* () {
217
- for (const x of xs) {
218
- if (!skip) {
219
- yield x;
216
+ });
217
+ const zs = xs.flatMap((x) => (skip ? [] : [x]));
218
+ `,
219
+ dedent`
220
+ import { Arr } from 'ts-data-forge';
221
+ declare const xs: readonly (number | undefined)[];
222
+ declare const skip: boolean;
223
+ const ys = Arr.generate(function* () {
224
+ for (const x of xs) {
225
+ if (x !== undefined) {
226
+ yield x;
227
+ }
220
228
  }
221
- }
222
- });
223
- `,
229
+ });
230
+ const zs = Arr.generate(function* () {
231
+ for (const x of xs) {
232
+ if (!skip) {
233
+ yield x;
234
+ }
235
+ }
236
+ });
237
+ `,
238
+ ],
224
239
  errors: [
225
240
  { messageId: 'useArrGenerate' },
226
241
  { messageId: 'useArrGenerate' },
@@ -237,40 +252,58 @@ describe('prefer-arr-generate', () => {
237
252
  const c = xs.flatMap((x) => (n < 0 ? [] : [x]));
238
253
  const d = xs.flatMap((x) => (!ok(x) ? [] : [x]));
239
254
  `,
240
- output: dedent`
241
- import { Arr } from 'ts-data-forge';
242
- declare const xs: readonly (string | undefined)[];
243
- declare const ok: (x: string | undefined) => boolean;
244
- declare const n: number;
245
- const a = Arr.generate(function* () {
246
- for (const x of xs) {
247
- if (x !== undefined && x !== '') {
248
- yield x;
255
+ output: [
256
+ dedent`
257
+ import { Arr } from 'ts-data-forge';
258
+ declare const xs: readonly (string | undefined)[];
259
+ declare const ok: (x: string | undefined) => boolean;
260
+ declare const n: number;
261
+ const a = Arr.generate(function* () {
262
+ for (const x of xs) {
263
+ if (x !== undefined && x !== '') {
264
+ yield x;
265
+ }
249
266
  }
250
- }
251
- });
252
- const b = Arr.generate(function* () {
253
- for (const x of xs) {
254
- if (!ok(x)) {
255
- yield x;
267
+ });
268
+ const b = xs.flatMap((x) => (ok(x) ? [] : [x]));
269
+ const c = xs.flatMap((x) => (n < 0 ? [] : [x]));
270
+ const d = xs.flatMap((x) => (!ok(x) ? [] : [x]));
271
+ `,
272
+ dedent`
273
+ import { Arr } from 'ts-data-forge';
274
+ declare const xs: readonly (string | undefined)[];
275
+ declare const ok: (x: string | undefined) => boolean;
276
+ declare const n: number;
277
+ const a = Arr.generate(function* () {
278
+ for (const x of xs) {
279
+ if (x !== undefined && x !== '') {
280
+ yield x;
281
+ }
256
282
  }
257
- }
258
- });
259
- const c = Arr.generate(function* () {
260
- for (const x of xs) {
261
- if (!(n < 0)) {
262
- yield x;
283
+ });
284
+ const b = Arr.generate(function* () {
285
+ for (const x of xs) {
286
+ if (!ok(x)) {
287
+ yield x;
288
+ }
263
289
  }
264
- }
265
- });
266
- const d = Arr.generate(function* () {
267
- for (const x of xs) {
268
- if (ok(x)) {
269
- yield x;
290
+ });
291
+ const c = Arr.generate(function* () {
292
+ for (const x of xs) {
293
+ if (!(n < 0)) {
294
+ yield x;
295
+ }
270
296
  }
271
- }
272
- });
273
- `,
297
+ });
298
+ const d = Arr.generate(function* () {
299
+ for (const x of xs) {
300
+ if (ok(x)) {
301
+ yield x;
302
+ }
303
+ }
304
+ });
305
+ `,
306
+ ],
274
307
  errors: [
275
308
  { messageId: 'useArrGenerate' },
276
309
  { messageId: 'useArrGenerate' },
@@ -435,6 +468,25 @@ describe('prefer-arr-generate', () => {
435
468
  `,
436
469
  errors: [{ messageId: 'useArrGenerate' }],
437
470
  },
471
+ {
472
+ name: 'no fix when an import type binds Arr',
473
+ code: dedent`
474
+ import type { Arr } from 'ts-data-forge';
475
+ declare const xs: readonly number[];
476
+ const ys = xs.flatMap((x) => (x > 0 ? [x] : []));
477
+ `,
478
+ output: null,
479
+ errors: [{ messageId: 'useArrGenerate' }],
480
+ },
481
+ {
482
+ name: 'no fix where a local binding takes Arr',
483
+ code: dedent`
484
+ declare const xs: readonly number[];
485
+ export const f = (Arr: unknown) => xs.flatMap((x) => (x > 0 ? [x] : []));
486
+ `,
487
+ output: null,
488
+ errors: [{ messageId: 'useArrGenerate' }],
489
+ },
438
490
  {
439
491
  name: 'indents from the line the call starts on, and accepts a mutable array, a tuple or a type parameter',
440
492
  code: dedent`
@@ -446,34 +498,52 @@ describe('prefer-arr-generate', () => {
446
498
  const c = xs.flatMap((x) => (x > 0 ? [x] : []));
447
499
  };
448
500
  `,
449
- output: dedent`
450
- import { Arr } from 'ts-data-forge';
451
- declare const ms: number[];
452
- declare const ts: readonly [number, number];
453
- export const f = <T extends readonly number[]>(xs: T): void => {
454
- const a = Arr.generate(function* () {
455
- for (const x of ms) {
456
- if (x > 0) {
457
- yield x;
501
+ output: [
502
+ dedent`
503
+ import { Arr } from 'ts-data-forge';
504
+ declare const ms: number[];
505
+ declare const ts: readonly [number, number];
506
+ export const f = <T extends readonly number[]>(xs: T): void => {
507
+ const a = Arr.generate(function* () {
508
+ for (const x of ms) {
509
+ if (x > 0) {
510
+ yield x;
511
+ }
458
512
  }
459
- }
460
- });
461
- const b = Arr.generate(function* () {
462
- for (const x of ts) {
463
- if (x > 0) {
464
- yield x;
513
+ });
514
+ const b = ts.flatMap((x) => (x > 0 ? [x] : []));
515
+ const c = xs.flatMap((x) => (x > 0 ? [x] : []));
516
+ };
517
+ `,
518
+ dedent`
519
+ import { Arr } from 'ts-data-forge';
520
+ declare const ms: number[];
521
+ declare const ts: readonly [number, number];
522
+ export const f = <T extends readonly number[]>(xs: T): void => {
523
+ const a = Arr.generate(function* () {
524
+ for (const x of ms) {
525
+ if (x > 0) {
526
+ yield x;
527
+ }
465
528
  }
466
- }
467
- });
468
- const c = Arr.generate(function* () {
469
- for (const x of xs) {
470
- if (x > 0) {
471
- yield x;
529
+ });
530
+ const b = Arr.generate(function* () {
531
+ for (const x of ts) {
532
+ if (x > 0) {
533
+ yield x;
534
+ }
472
535
  }
473
- }
474
- });
475
- };
476
- `,
536
+ });
537
+ const c = Arr.generate(function* () {
538
+ for (const x of xs) {
539
+ if (x > 0) {
540
+ yield x;
541
+ }
542
+ }
543
+ });
544
+ };
545
+ `,
546
+ ],
477
547
  errors: [
478
548
  { messageId: 'useArrGenerate' },
479
549
  { messageId: 'useArrGenerate' },
@@ -691,30 +761,50 @@ describe('prefer-arr-generate', () => {
691
761
  return [...a, ...b];
692
762
  };
693
763
  `,
694
- output: dedent`
695
- import { Arr } from 'ts-data-forge';
696
- declare const c: readonly number[] | undefined;
697
- export const f = (p: readonly number[] | undefined): readonly number[] => {
698
- if (c === undefined || p === undefined) {
699
- return [];
700
- }
701
- const a = Arr.generate(function* () {
702
- for (const x of c) {
703
- if (x > 0) {
704
- yield x;
705
- }
764
+ output: [
765
+ dedent`
766
+ import { Arr } from 'ts-data-forge';
767
+ declare const c: readonly number[] | undefined;
768
+ export const f = (p: readonly number[] | undefined): readonly number[] => {
769
+ if (c === undefined || p === undefined) {
770
+ return [];
706
771
  }
707
- });
708
- const b = Arr.generate(function* () {
709
- for (const x of p) {
710
- if (x > 0) {
711
- yield x;
772
+ const a = Arr.generate(function* () {
773
+ for (const x of c) {
774
+ if (x > 0) {
775
+ yield x;
776
+ }
712
777
  }
778
+ });
779
+ const b = p.flatMap((x) => (x > 0 ? [x] : []));
780
+ return [...a, ...b];
781
+ };
782
+ `,
783
+ dedent`
784
+ import { Arr } from 'ts-data-forge';
785
+ declare const c: readonly number[] | undefined;
786
+ export const f = (p: readonly number[] | undefined): readonly number[] => {
787
+ if (c === undefined || p === undefined) {
788
+ return [];
713
789
  }
714
- });
715
- return [...a, ...b];
716
- };
717
- `,
790
+ const a = Arr.generate(function* () {
791
+ for (const x of c) {
792
+ if (x > 0) {
793
+ yield x;
794
+ }
795
+ }
796
+ });
797
+ const b = Arr.generate(function* () {
798
+ for (const x of p) {
799
+ if (x > 0) {
800
+ yield x;
801
+ }
802
+ }
803
+ });
804
+ return [...a, ...b];
805
+ };
806
+ `,
807
+ ],
718
808
  errors: [
719
809
  { messageId: 'useArrGenerate' },
720
810
  { messageId: 'useArrGenerate' },
@@ -737,39 +827,292 @@ describe('prefer-arr-generate', () => {
737
827
  return [...a, ...b];
738
828
  };
739
829
  `,
740
- output: dedent`
741
- import { Arr } from 'ts-data-forge';
742
- declare const isNonEmpty: <T,>(
743
- xs: readonly T[],
744
- ) => xs is readonly [T, ...T[]];
745
- declare const o: Readonly<{ names: readonly string[] }>;
746
- declare const nested: readonly (readonly string[])[];
747
- export const f = (): readonly string[] => {
748
- if (!isNonEmpty(o.names)) {
749
- return [];
750
- }
751
- const a = Arr.generate(function* () {
752
- for (const x of o.names) {
753
- if (x !== '') {
754
- yield x;
830
+ output: [
831
+ dedent`
832
+ import { Arr } from 'ts-data-forge';
833
+ declare const isNonEmpty: <T,>(
834
+ xs: readonly T[],
835
+ ) => xs is readonly [T, ...T[]];
836
+ declare const o: Readonly<{ names: readonly string[] }>;
837
+ declare const nested: readonly (readonly string[])[];
838
+ export const f = (): readonly string[] => {
839
+ if (!isNonEmpty(o.names)) {
840
+ return [];
841
+ }
842
+ const a = Arr.generate(function* () {
843
+ for (const x of o.names) {
844
+ if (x !== '') {
845
+ yield x;
846
+ }
755
847
  }
848
+ });
849
+ const b = nested.flat().flatMap((x) => (x !== '' ? [x] : []));
850
+ return [...a, ...b];
851
+ };
852
+ `,
853
+ dedent`
854
+ import { Arr } from 'ts-data-forge';
855
+ declare const isNonEmpty: <T,>(
856
+ xs: readonly T[],
857
+ ) => xs is readonly [T, ...T[]];
858
+ declare const o: Readonly<{ names: readonly string[] }>;
859
+ declare const nested: readonly (readonly string[])[];
860
+ export const f = (): readonly string[] => {
861
+ if (!isNonEmpty(o.names)) {
862
+ return [];
756
863
  }
757
- });
758
- const b = Arr.generate(function* () {
759
- for (const x of nested.flat()) {
760
- if (x !== '') {
761
- yield x;
864
+ const a = Arr.generate(function* () {
865
+ for (const x of o.names) {
866
+ if (x !== '') {
867
+ yield x;
868
+ }
762
869
  }
870
+ });
871
+ const b = Arr.generate(function* () {
872
+ for (const x of nested.flat()) {
873
+ if (x !== '') {
874
+ yield x;
875
+ }
876
+ }
877
+ });
878
+ return [...a, ...b];
879
+ };
880
+ `,
881
+ ],
882
+ errors: [
883
+ { messageId: 'useArrGenerate' },
884
+ { messageId: 'useArrGenerate' },
885
+ ],
886
+ },
887
+ {
888
+ name: 'only suggests when a comment between the receiver and `.flatMap` would be lost',
889
+ code: dedent`
890
+ declare const xs: readonly number[];
891
+ const ys = xs
892
+ // keep only the positives
893
+ .flatMap((x) => (x > 0 ? [x] : []));
894
+ `,
895
+ output: null,
896
+ errors: [
897
+ {
898
+ messageId: 'useArrGenerate',
899
+ suggestions: [
900
+ {
901
+ messageId: 'suggestArrGenerate',
902
+ output: dedent`
903
+ import { Arr } from 'ts-data-forge';
904
+ declare const xs: readonly number[];
905
+ const ys = Arr.generate(function* () {
906
+ for (const x of xs) {
907
+ if (x > 0) {
908
+ yield x;
909
+ }
910
+ }
911
+ });
912
+ `,
913
+ },
914
+ ],
915
+ },
916
+ ],
917
+ },
918
+ {
919
+ name: 'only suggests when a comment after `flatMap(` would be lost',
920
+ code: dedent`
921
+ declare const xs: readonly number[];
922
+ const ys = xs.flatMap(
923
+ // keep only the positives
924
+ (x) => (x > 0 ? [x] : []),
925
+ );
926
+ `,
927
+ output: null,
928
+ errors: [
929
+ {
930
+ messageId: 'useArrGenerate',
931
+ suggestions: [
932
+ {
933
+ messageId: 'suggestArrGenerate',
934
+ output: dedent`
935
+ import { Arr } from 'ts-data-forge';
936
+ declare const xs: readonly number[];
937
+ const ys = Arr.generate(function* () {
938
+ for (const x of xs) {
939
+ if (x > 0) {
940
+ yield x;
941
+ }
942
+ }
943
+ });
944
+ `,
945
+ },
946
+ ],
947
+ },
948
+ ],
949
+ },
950
+ {
951
+ name: 'only suggests when a comment after the callback, before `)` would be lost',
952
+ code: dedent`
953
+ declare const xs: readonly number[];
954
+ const ys = xs.flatMap(
955
+ (x) => (x > 0 ? [x] : []),
956
+ // keep only the positives
957
+ );
958
+ `,
959
+ output: null,
960
+ errors: [
961
+ {
962
+ messageId: 'useArrGenerate',
963
+ suggestions: [
964
+ {
965
+ messageId: 'suggestArrGenerate',
966
+ output: dedent`
967
+ import { Arr } from 'ts-data-forge';
968
+ declare const xs: readonly number[];
969
+ const ys = Arr.generate(function* () {
970
+ for (const x of xs) {
971
+ if (x > 0) {
972
+ yield x;
973
+ }
974
+ }
975
+ });
976
+ `,
977
+ },
978
+ ],
979
+ },
980
+ ],
981
+ },
982
+ {
983
+ name: 'keeps the fix automatic when the comment is inside the carried type argument',
984
+ code: dedent`
985
+ declare const xs: readonly number[];
986
+ const ys = xs.flatMap</* positives */ number>((x) => (x > 0 ? [x] : []));
987
+ `,
988
+ output: dedent`
989
+ import { Arr } from 'ts-data-forge';
990
+ declare const xs: readonly number[];
991
+ const ys = Arr.generate</* positives */ number>(function* () {
992
+ for (const x of xs) {
993
+ if (x > 0) {
994
+ yield x;
763
995
  }
996
+ }
997
+ });
998
+ `,
999
+ errors: [{ messageId: 'useArrGenerate' }],
1000
+ },
1001
+ {
1002
+ name: 'keeps the fix automatic when the comment is inside the receiver or the parameter',
1003
+ code: dedent`
1004
+ declare const f: (a: readonly { a: number }[]) => readonly { a: number }[];
1005
+ declare const xs: readonly { a: number }[];
1006
+ const ys = f(/* all */ xs).flatMap(({ a /* the value */ }) => (a > 0 ? [a] : []));
1007
+ `,
1008
+ output: dedent`
1009
+ import { Arr } from 'ts-data-forge';
1010
+ declare const f: (a: readonly { a: number }[]) => readonly { a: number }[];
1011
+ declare const xs: readonly { a: number }[];
1012
+ const ys = Arr.generate(function* () {
1013
+ for (const { a /* the value */ } of f(/* all */ xs)) {
1014
+ if (a > 0) {
1015
+ yield a;
1016
+ }
1017
+ }
1018
+ });
1019
+ `,
1020
+ errors: [{ messageId: 'useArrGenerate' }],
1021
+ },
1022
+ {
1023
+ name: 'only suggests when a comment in a negated test would be lost',
1024
+ code: dedent`
1025
+ declare const xs: readonly number[];
1026
+ const ys = xs.flatMap((x) => (x > 0 && /* small */ x < 9 ? [] : [x]));
1027
+ `,
1028
+ output: null,
1029
+ errors: [
1030
+ {
1031
+ messageId: 'useArrGenerate',
1032
+ suggestions: [
1033
+ {
1034
+ messageId: 'suggestArrGenerate',
1035
+ output: dedent`
1036
+ import { Arr } from 'ts-data-forge';
1037
+ declare const xs: readonly number[];
1038
+ const ys = Arr.generate(function* () {
1039
+ for (const x of xs) {
1040
+ if (!(x > 0) || !(x < 9)) {
1041
+ yield x;
1042
+ }
1043
+ }
1044
+ });
1045
+ `,
1046
+ },
1047
+ ],
1048
+ },
1049
+ ],
1050
+ },
1051
+ {
1052
+ name: 'only suggests when a comment before `.flatMap` would be lost, even if a kept comment starts with the same text',
1053
+ code: dedent`
1054
+ declare const xs: readonly number[];
1055
+ const ys = xs // TODO
1056
+ .flatMap((x) => {
1057
+ // TODO: check this
1058
+ const y = x + 1;
1059
+ return y > 0 ? [y] : [];
764
1060
  });
765
- return [...a, ...b];
766
- };
767
1061
  `,
1062
+ output: null,
768
1063
  errors: [
769
- { messageId: 'useArrGenerate' },
770
- { messageId: 'useArrGenerate' },
1064
+ {
1065
+ messageId: 'useArrGenerate',
1066
+ suggestions: [
1067
+ {
1068
+ messageId: 'suggestArrGenerate',
1069
+ output: dedent`
1070
+ import { Arr } from 'ts-data-forge';
1071
+ declare const xs: readonly number[];
1072
+ const ys = Arr.generate(function* () {
1073
+ for (const x of xs) {
1074
+ // TODO: check this
1075
+ const y = x + 1;
1076
+ if (y > 0) {
1077
+ yield y;
1078
+ }
1079
+ }
1080
+ });
1081
+ `,
1082
+ },
1083
+ ],
1084
+ },
771
1085
  ],
772
1086
  },
1087
+ {
1088
+ name: 'keeps the fix automatic for a multi-line comment in the prelude',
1089
+ code: dedent`
1090
+ declare const xs: readonly number[];
1091
+ const ys = xs.flatMap((x) => {
1092
+ /*
1093
+ * Odd ones only.
1094
+ */
1095
+ const y = x;
1096
+ return y % 2 === 1 ? [y] : [];
1097
+ });
1098
+ `,
1099
+ output: dedent`
1100
+ import { Arr } from 'ts-data-forge';
1101
+ declare const xs: readonly number[];
1102
+ const ys = Arr.generate(function* () {
1103
+ for (const x of xs) {
1104
+ /*
1105
+ * Odd ones only.
1106
+ */
1107
+ const y = x;
1108
+ if (y % 2 === 1) {
1109
+ yield y;
1110
+ }
1111
+ }
1112
+ });
1113
+ `,
1114
+ errors: [{ messageId: 'useArrGenerate' }],
1115
+ },
773
1116
  {
774
1117
  name: 'only suggests when a comment would be lost',
775
1118
  code: dedent`
@@ -867,24 +1210,38 @@ describe('prefer-arr-generate through type wrappers', () => {
867
1210
  );
868
1211
  const b = xs.flatMap!((x) => (x > 0 ? [x] : []));
869
1212
  `,
870
- output: dedent`
871
- import { Arr } from 'ts-data-forge';
872
- declare const xs: readonly number[];
873
- const a = Arr.generate(function* () {
874
- for (const x of xs satisfies readonly number[]) {
875
- if (x > 0) {
876
- yield x;
1213
+ output: [
1214
+ dedent`
1215
+ import { Arr } from 'ts-data-forge';
1216
+ declare const xs: readonly number[];
1217
+ const a = Arr.generate(function* () {
1218
+ for (const x of xs satisfies readonly number[]) {
1219
+ if (x > 0) {
1220
+ yield x;
1221
+ }
877
1222
  }
878
- }
879
- });
880
- const b = Arr.generate(function* () {
881
- for (const x of xs) {
882
- if (x > 0) {
883
- yield x;
1223
+ });
1224
+ const b = xs.flatMap!((x) => (x > 0 ? [x] : []));
1225
+ `,
1226
+ dedent`
1227
+ import { Arr } from 'ts-data-forge';
1228
+ declare const xs: readonly number[];
1229
+ const a = Arr.generate(function* () {
1230
+ for (const x of xs satisfies readonly number[]) {
1231
+ if (x > 0) {
1232
+ yield x;
1233
+ }
884
1234
  }
885
- }
886
- });
887
- `,
1235
+ });
1236
+ const b = Arr.generate(function* () {
1237
+ for (const x of xs) {
1238
+ if (x > 0) {
1239
+ yield x;
1240
+ }
1241
+ }
1242
+ });
1243
+ `,
1244
+ ],
888
1245
  errors: [
889
1246
  { messageId: 'useArrGenerate' },
890
1247
  { messageId: 'useArrGenerate' },