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
@@ -21,7 +21,7 @@ describe('prefer-num-safe-parse-float', () => {
21
21
  tester.run('prefer-num-safe-parse-float', preferNumSafeParseFloat, {
22
22
  valid: [
23
23
  {
24
- name: 'ignores number arguments to Number() (autofix would be unsafe)',
24
+ name: 'ignores number arguments to Number() (the rewrite would be unsafe)',
25
25
  code: dedent`
26
26
  const x = 42;
27
27
  const n = Number(x);
@@ -58,17 +58,74 @@ describe('prefer-num-safe-parse-float', () => {
58
58
  ],
59
59
  invalid: [
60
60
  {
61
- name: 'replaces parseFloat(s) and imports Num + Result',
61
+ name: 'offers no suggestion when `Result` is bound to another module',
62
62
  code: dedent`
63
- const s = "3.14";
63
+ import { Result } from 'other-lib';
64
+
65
+ declare const s: string;
64
66
  const n = parseFloat(s);
67
+ export const r = Result;
65
68
  `,
66
- output: dedent`
67
- import { Num, Result } from 'ts-data-forge';
69
+ errors: [{ messageId: 'useSafeParseFloat', suggestions: [] }],
70
+ },
71
+ {
72
+ // The replacement reads these strings differently ('12px' is NaN, not
73
+ // 12; '' is NaN, not 0), so it is offered, never applied by --fix
74
+ name: 'a string the replacement parses differently is a suggestion, not a fix',
75
+ code: dedent`
76
+ const a = parseFloat('12px');
77
+ const b = Number('');
78
+ `,
79
+ errors: [
80
+ {
81
+ messageId: 'useSafeParseFloat',
82
+ suggestions: [
83
+ {
84
+ messageId: 'replaceWithSafeParse',
85
+ output: dedent`
86
+ import { Num, Result } from 'ts-data-forge';
87
+ const a = Result.unwrapOkOr(Num.safeParseFloat('12px'), Number.NaN);
88
+ const b = Number('');
89
+ `,
90
+ },
91
+ ],
92
+ },
93
+ {
94
+ messageId: 'useSafeParseFloat',
95
+ suggestions: [
96
+ {
97
+ messageId: 'replaceWithSafeParse',
98
+ output: dedent`
99
+ import { Num, Result } from 'ts-data-forge';
100
+ const a = parseFloat('12px');
101
+ const b = Result.unwrapOkOr(Num.safeParseFloat(''), Number.NaN);
102
+ `,
103
+ },
104
+ ],
105
+ },
106
+ ],
107
+ },
108
+ {
109
+ name: 'replaces parseFloat(s) and imports Num + Result',
110
+ code: dedent`
68
111
  const s = "3.14";
69
- const n = Result.unwrapOkOr(Num.safeParseFloat(s), Number.NaN);
112
+ const n = parseFloat(s);
70
113
  `,
71
- errors: [{ messageId: 'useSafeParseFloat' }],
114
+ errors: [
115
+ {
116
+ messageId: 'useSafeParseFloat',
117
+ suggestions: [
118
+ {
119
+ messageId: 'replaceWithSafeParse',
120
+ output: dedent`
121
+ import { Num, Result } from 'ts-data-forge';
122
+ const s = "3.14";
123
+ const n = Result.unwrapOkOr(Num.safeParseFloat(s), Number.NaN);
124
+ `,
125
+ },
126
+ ],
127
+ },
128
+ ],
72
129
  },
73
130
  {
74
131
  name: 'replaces Number.parseFloat(s)',
@@ -76,12 +133,21 @@ describe('prefer-num-safe-parse-float', () => {
76
133
  const s = "3.14";
77
134
  const n = Number.parseFloat(s);
78
135
  `,
79
- output: dedent`
80
- import { Num, Result } from 'ts-data-forge';
81
- const s = "3.14";
82
- const n = Result.unwrapOkOr(Num.safeParseFloat(s), Number.NaN);
83
- `,
84
- errors: [{ messageId: 'useSafeParseFloat' }],
136
+ errors: [
137
+ {
138
+ messageId: 'useSafeParseFloat',
139
+ suggestions: [
140
+ {
141
+ messageId: 'replaceWithSafeParse',
142
+ output: dedent`
143
+ import { Num, Result } from 'ts-data-forge';
144
+ const s = "3.14";
145
+ const n = Result.unwrapOkOr(Num.safeParseFloat(s), Number.NaN);
146
+ `,
147
+ },
148
+ ],
149
+ },
150
+ ],
85
151
  },
86
152
  {
87
153
  name: 'replaces Number(s) when s is a string',
@@ -89,12 +155,21 @@ describe('prefer-num-safe-parse-float', () => {
89
155
  const s = "3.14";
90
156
  const n = Number(s);
91
157
  `,
92
- output: dedent`
93
- import { Num, Result } from 'ts-data-forge';
94
- const s = "3.14";
95
- const n = Result.unwrapOkOr(Num.safeParseFloat(s), Number.NaN);
96
- `,
97
- errors: [{ messageId: 'useSafeParseFloat' }],
158
+ errors: [
159
+ {
160
+ messageId: 'useSafeParseFloat',
161
+ suggestions: [
162
+ {
163
+ messageId: 'replaceWithSafeParse',
164
+ output: dedent`
165
+ import { Num, Result } from 'ts-data-forge';
166
+ const s = "3.14";
167
+ const n = Result.unwrapOkOr(Num.safeParseFloat(s), Number.NaN);
168
+ `,
169
+ },
170
+ ],
171
+ },
172
+ ],
98
173
  },
99
174
  {
100
175
  name: 'adds only the missing Result import when Num is present',
@@ -104,13 +179,22 @@ describe('prefer-num-safe-parse-float', () => {
104
179
  const s = "3.14";
105
180
  const n = parseFloat(s);
106
181
  `,
107
- output: dedent`
108
- import { Num, Result } from 'ts-data-forge';
182
+ errors: [
183
+ {
184
+ messageId: 'useSafeParseFloat',
185
+ suggestions: [
186
+ {
187
+ messageId: 'replaceWithSafeParse',
188
+ output: dedent`
189
+ import { Num, Result } from 'ts-data-forge';
109
190
 
110
- const s = "3.14";
111
- const n = Result.unwrapOkOr(Num.safeParseFloat(s), Number.NaN);
112
- `,
113
- errors: [{ messageId: 'useSafeParseFloat' }],
191
+ const s = "3.14";
192
+ const n = Result.unwrapOkOr(Num.safeParseFloat(s), Number.NaN);
193
+ `,
194
+ },
195
+ ],
196
+ },
197
+ ],
114
198
  },
115
199
  {
116
200
  name: 'preserves a complex string argument expression',
@@ -118,23 +202,41 @@ describe('prefer-num-safe-parse-float', () => {
118
202
  const get = (k: string): string => k;
119
203
  const n = parseFloat(get("x").trim());
120
204
  `,
121
- output: dedent`
122
- import { Num, Result } from 'ts-data-forge';
123
- const get = (k: string): string => k;
124
- const n = Result.unwrapOkOr(Num.safeParseFloat(get("x").trim()), Number.NaN);
125
- `,
126
- errors: [{ messageId: 'useSafeParseFloat' }],
205
+ errors: [
206
+ {
207
+ messageId: 'useSafeParseFloat',
208
+ suggestions: [
209
+ {
210
+ messageId: 'replaceWithSafeParse',
211
+ output: dedent`
212
+ import { Num, Result } from 'ts-data-forge';
213
+ const get = (k: string): string => k;
214
+ const n = Result.unwrapOkOr(Num.safeParseFloat(get("x").trim()), Number.NaN);
215
+ `,
216
+ },
217
+ ],
218
+ },
219
+ ],
127
220
  },
128
221
  {
129
222
  name: 'replaces Number(s) with a string literal argument',
130
223
  code: dedent`
131
224
  const n = Number("3.14");
132
225
  `,
133
- output: dedent`
134
- import { Num, Result } from 'ts-data-forge';
135
- const n = Result.unwrapOkOr(Num.safeParseFloat("3.14"), Number.NaN);
136
- `,
137
- errors: [{ messageId: 'useSafeParseFloat' }],
226
+ errors: [
227
+ {
228
+ messageId: 'useSafeParseFloat',
229
+ suggestions: [
230
+ {
231
+ messageId: 'replaceWithSafeParse',
232
+ output: dedent`
233
+ import { Num, Result } from 'ts-data-forge';
234
+ const n = Result.unwrapOkOr(Num.safeParseFloat("3.14"), Number.NaN);
235
+ `,
236
+ },
237
+ ],
238
+ },
239
+ ],
138
240
  },
139
241
  {
140
242
  name: 'replaces all three forms in one file',
@@ -144,26 +246,52 @@ describe('prefer-num-safe-parse-float', () => {
144
246
  const b = Number.parseFloat(s);
145
247
  const c = Number(s);
146
248
  `,
147
- output: [
148
- dedent`
149
- import { Num, Result } from 'ts-data-forge';
150
- const s = "1.5";
151
- const a = Result.unwrapOkOr(Num.safeParseFloat(s), Number.NaN);
152
- const b = Number.parseFloat(s);
153
- const c = Number(s);
154
- `,
155
- dedent`
156
- import { Num, Result } from 'ts-data-forge';
157
- const s = "1.5";
158
- const a = Result.unwrapOkOr(Num.safeParseFloat(s), Number.NaN);
159
- const b = Result.unwrapOkOr(Num.safeParseFloat(s), Number.NaN);
160
- const c = Result.unwrapOkOr(Num.safeParseFloat(s), Number.NaN);
161
- `,
162
- ],
163
249
  errors: [
164
- { messageId: 'useSafeParseFloat' },
165
- { messageId: 'useSafeParseFloat' },
166
- { messageId: 'useSafeParseFloat' },
250
+ {
251
+ messageId: 'useSafeParseFloat',
252
+ suggestions: [
253
+ {
254
+ messageId: 'replaceWithSafeParse',
255
+ output: dedent`
256
+ import { Num, Result } from 'ts-data-forge';
257
+ const s = "1.5";
258
+ const a = Result.unwrapOkOr(Num.safeParseFloat(s), Number.NaN);
259
+ const b = Number.parseFloat(s);
260
+ const c = Number(s);
261
+ `,
262
+ },
263
+ ],
264
+ },
265
+ {
266
+ messageId: 'useSafeParseFloat',
267
+ suggestions: [
268
+ {
269
+ messageId: 'replaceWithSafeParse',
270
+ output: dedent`
271
+ import { Num, Result } from 'ts-data-forge';
272
+ const s = "1.5";
273
+ const a = parseFloat(s);
274
+ const b = Result.unwrapOkOr(Num.safeParseFloat(s), Number.NaN);
275
+ const c = Number(s);
276
+ `,
277
+ },
278
+ ],
279
+ },
280
+ {
281
+ messageId: 'useSafeParseFloat',
282
+ suggestions: [
283
+ {
284
+ messageId: 'replaceWithSafeParse',
285
+ output: dedent`
286
+ import { Num, Result } from 'ts-data-forge';
287
+ const s = "1.5";
288
+ const a = parseFloat(s);
289
+ const b = Number.parseFloat(s);
290
+ const c = Result.unwrapOkOr(Num.safeParseFloat(s), Number.NaN);
291
+ `,
292
+ },
293
+ ],
294
+ },
167
295
  ],
168
296
  },
169
297
  ],
@@ -211,23 +339,35 @@ describe('prefer-num-safe-parse-float through type wrappers', () => {
211
339
  const a = Number(s!);
212
340
  const b = parseFloat(s satisfies string);
213
341
  `,
214
- output: [
215
- dedent`
216
- import { Num, Result } from 'ts-data-forge';
217
- declare const s: string;
218
- const a = Result.unwrapOkOr(Num.safeParseFloat(s!), Number.NaN);
219
- const b = parseFloat(s satisfies string);
220
- `,
221
- dedent`
222
- import { Num, Result } from 'ts-data-forge';
223
- declare const s: string;
224
- const a = Result.unwrapOkOr(Num.safeParseFloat(s!), Number.NaN);
225
- const b = Result.unwrapOkOr(Num.safeParseFloat(s satisfies string), Number.NaN);
226
- `,
227
- ],
228
342
  errors: [
229
- { messageId: 'useSafeParseFloat' },
230
- { messageId: 'useSafeParseFloat' },
343
+ {
344
+ messageId: 'useSafeParseFloat',
345
+ suggestions: [
346
+ {
347
+ messageId: 'replaceWithSafeParse',
348
+ output: dedent`
349
+ import { Num, Result } from 'ts-data-forge';
350
+ declare const s: string;
351
+ const a = Result.unwrapOkOr(Num.safeParseFloat(s!), Number.NaN);
352
+ const b = parseFloat(s satisfies string);
353
+ `,
354
+ },
355
+ ],
356
+ },
357
+ {
358
+ messageId: 'useSafeParseFloat',
359
+ suggestions: [
360
+ {
361
+ messageId: 'replaceWithSafeParse',
362
+ output: dedent`
363
+ import { Num, Result } from 'ts-data-forge';
364
+ declare const s: string;
365
+ const a = Number(s!);
366
+ const b = Result.unwrapOkOr(Num.safeParseFloat(s satisfies string), Number.NaN);
367
+ `,
368
+ },
369
+ ],
370
+ },
231
371
  ],
232
372
  },
233
373
  {
@@ -237,23 +377,35 @@ describe('prefer-num-safe-parse-float through type wrappers', () => {
237
377
  const a = (Number as NumberConstructor)(s);
238
378
  const b = Number!.parseFloat(s);
239
379
  `,
240
- output: [
241
- dedent`
242
- import { Num, Result } from 'ts-data-forge';
243
- declare const s: string;
244
- const a = Result.unwrapOkOr(Num.safeParseFloat(s), Number.NaN);
245
- const b = Number!.parseFloat(s);
246
- `,
247
- dedent`
248
- import { Num, Result } from 'ts-data-forge';
249
- declare const s: string;
250
- const a = Result.unwrapOkOr(Num.safeParseFloat(s), Number.NaN);
251
- const b = Result.unwrapOkOr(Num.safeParseFloat(s), Number.NaN);
252
- `,
253
- ],
254
380
  errors: [
255
- { messageId: 'useSafeParseFloat' },
256
- { messageId: 'useSafeParseFloat' },
381
+ {
382
+ messageId: 'useSafeParseFloat',
383
+ suggestions: [
384
+ {
385
+ messageId: 'replaceWithSafeParse',
386
+ output: dedent`
387
+ import { Num, Result } from 'ts-data-forge';
388
+ declare const s: string;
389
+ const a = Result.unwrapOkOr(Num.safeParseFloat(s), Number.NaN);
390
+ const b = Number!.parseFloat(s);
391
+ `,
392
+ },
393
+ ],
394
+ },
395
+ {
396
+ messageId: 'useSafeParseFloat',
397
+ suggestions: [
398
+ {
399
+ messageId: 'replaceWithSafeParse',
400
+ output: dedent`
401
+ import { Num, Result } from 'ts-data-forge';
402
+ declare const s: string;
403
+ const a = (Number as NumberConstructor)(s);
404
+ const b = Result.unwrapOkOr(Num.safeParseFloat(s), Number.NaN);
405
+ `,
406
+ },
407
+ ],
408
+ },
257
409
  ],
258
410
  },
259
411
  ],
@@ -271,13 +423,22 @@ describe('prefer-num-safe-parse-float with parenthesized operands', () => {
271
423
  declare const log: () => void;
272
424
  const a = Number((log(), s));
273
425
  `,
274
- output: dedent`
275
- import { Num, Result } from 'ts-data-forge';
276
- declare const s: string;
277
- declare const log: () => void;
278
- const a = Result.unwrapOkOr(Num.safeParseFloat((log(), s)), Number.NaN);
279
- `,
280
- errors: [{ messageId: 'useSafeParseFloat' }],
426
+ errors: [
427
+ {
428
+ messageId: 'useSafeParseFloat',
429
+ suggestions: [
430
+ {
431
+ messageId: 'replaceWithSafeParse',
432
+ output: dedent`
433
+ import { Num, Result } from 'ts-data-forge';
434
+ declare const s: string;
435
+ declare const log: () => void;
436
+ const a = Result.unwrapOkOr(Num.safeParseFloat((log(), s)), Number.NaN);
437
+ `,
438
+ },
439
+ ],
440
+ },
441
+ ],
281
442
  },
282
443
  ],
283
444
  });