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
@@ -28,7 +28,7 @@ describe('prefer-num-safe-parse-int', () => {
28
28
  `,
29
29
  },
30
30
  {
31
- name: 'ignores number arguments (autofix would be unsafe)',
31
+ name: 'ignores number arguments (the rewrite would be unsafe)',
32
32
  code: dedent`
33
33
  const x = 42;
34
34
  const n = parseInt(x, 10);
@@ -50,18 +50,76 @@ describe('prefer-num-safe-parse-int', () => {
50
50
  },
51
51
  ],
52
52
  invalid: [
53
+ {
54
+ name: 'offers no suggestion when `Result` is bound to another module',
55
+ code: dedent`
56
+ import { Result } from 'other-lib';
57
+
58
+ declare const s: string;
59
+ const n = parseInt(s);
60
+ export const r = Result;
61
+ `,
62
+ errors: [{ messageId: 'useSafeParseInt', suggestions: [] }],
63
+ },
64
+ {
65
+ // The replacement reads these strings differently ('1e3' is 1000, not
66
+ // 1; '12px' is NaN, not 12), so it is offered, never applied by
67
+ // --fix
68
+ name: 'a string the replacement parses differently is a suggestion, not a fix',
69
+ code: dedent`
70
+ const a = parseInt('1e3');
71
+ const b = parseInt('12px', 10);
72
+ `,
73
+ errors: [
74
+ {
75
+ messageId: 'useSafeParseInt',
76
+ suggestions: [
77
+ {
78
+ messageId: 'replaceWithSafeParse',
79
+ output: dedent`
80
+ import { Num, Result } from 'ts-data-forge';
81
+ const a = Result.unwrapOkOr(Num.safeParseInt('1e3'), Number.NaN);
82
+ const b = parseInt('12px', 10);
83
+ `,
84
+ },
85
+ ],
86
+ },
87
+ {
88
+ messageId: 'useSafeParseInt',
89
+ suggestions: [
90
+ {
91
+ messageId: 'replaceWithSafeParse',
92
+ output: dedent`
93
+ import { Num, Result } from 'ts-data-forge';
94
+ const a = parseInt('1e3');
95
+ const b = Result.unwrapOkOr(Num.safeParseInt('12px'), Number.NaN);
96
+ `,
97
+ },
98
+ ],
99
+ },
100
+ ],
101
+ },
53
102
  {
54
103
  name: 'replaces parseInt(s, 10) and imports Num + Result',
55
104
  code: dedent`
56
105
  const s = "123";
57
106
  const n = parseInt(s, 10);
58
107
  `,
59
- output: dedent`
60
- import { Num, Result } from 'ts-data-forge';
61
- const s = "123";
62
- const n = Result.unwrapOkOr(Num.safeParseInt(s), Number.NaN);
63
- `,
64
- errors: [{ messageId: 'useSafeParseInt' }],
108
+ errors: [
109
+ {
110
+ messageId: 'useSafeParseInt',
111
+ suggestions: [
112
+ {
113
+ messageId: 'replaceWithSafeParse',
114
+ output: dedent`
115
+ import { Num, Result } from 'ts-data-forge';
116
+ const s = "123";
117
+ const n = Result.unwrapOkOr(Num.safeParseInt(s), Number.NaN);
118
+ `,
119
+ },
120
+ ],
121
+ },
122
+ ],
65
123
  },
66
124
  {
67
125
  name: 'replaces parseInt(s) without radix',
@@ -69,12 +127,21 @@ describe('prefer-num-safe-parse-int', () => {
69
127
  const s = "123";
70
128
  const n = parseInt(s);
71
129
  `,
72
- output: dedent`
73
- import { Num, Result } from 'ts-data-forge';
74
- const s = "123";
75
- const n = Result.unwrapOkOr(Num.safeParseInt(s), Number.NaN);
76
- `,
77
- errors: [{ messageId: 'useSafeParseInt' }],
130
+ errors: [
131
+ {
132
+ messageId: 'useSafeParseInt',
133
+ suggestions: [
134
+ {
135
+ messageId: 'replaceWithSafeParse',
136
+ output: dedent`
137
+ import { Num, Result } from 'ts-data-forge';
138
+ const s = "123";
139
+ const n = Result.unwrapOkOr(Num.safeParseInt(s), Number.NaN);
140
+ `,
141
+ },
142
+ ],
143
+ },
144
+ ],
78
145
  },
79
146
  {
80
147
  name: 'replaces Number.parseInt(s, 10)',
@@ -82,12 +149,21 @@ describe('prefer-num-safe-parse-int', () => {
82
149
  const s = "123";
83
150
  const n = Number.parseInt(s, 10);
84
151
  `,
85
- output: dedent`
86
- import { Num, Result } from 'ts-data-forge';
87
- const s = "123";
88
- const n = Result.unwrapOkOr(Num.safeParseInt(s), Number.NaN);
89
- `,
90
- errors: [{ messageId: 'useSafeParseInt' }],
152
+ errors: [
153
+ {
154
+ messageId: 'useSafeParseInt',
155
+ suggestions: [
156
+ {
157
+ messageId: 'replaceWithSafeParse',
158
+ output: dedent`
159
+ import { Num, Result } from 'ts-data-forge';
160
+ const s = "123";
161
+ const n = Result.unwrapOkOr(Num.safeParseInt(s), Number.NaN);
162
+ `,
163
+ },
164
+ ],
165
+ },
166
+ ],
91
167
  },
92
168
  {
93
169
  name: 'adds only the missing Result import when Num is present',
@@ -97,13 +173,22 @@ describe('prefer-num-safe-parse-int', () => {
97
173
  const s = "123";
98
174
  const n = parseInt(s, 10);
99
175
  `,
100
- output: dedent`
101
- import { Num, Result } from 'ts-data-forge';
176
+ errors: [
177
+ {
178
+ messageId: 'useSafeParseInt',
179
+ suggestions: [
180
+ {
181
+ messageId: 'replaceWithSafeParse',
182
+ output: dedent`
183
+ import { Num, Result } from 'ts-data-forge';
102
184
 
103
- const s = "123";
104
- const n = Result.unwrapOkOr(Num.safeParseInt(s), Number.NaN);
105
- `,
106
- errors: [{ messageId: 'useSafeParseInt' }],
185
+ const s = "123";
186
+ const n = Result.unwrapOkOr(Num.safeParseInt(s), Number.NaN);
187
+ `,
188
+ },
189
+ ],
190
+ },
191
+ ],
107
192
  },
108
193
  {
109
194
  name: 'wraps in parentheses in an operator context',
@@ -111,12 +196,21 @@ describe('prefer-num-safe-parse-int', () => {
111
196
  const s = "123";
112
197
  const ok = parseInt(s, 10) > 5;
113
198
  `,
114
- output: dedent`
115
- import { Num, Result } from 'ts-data-forge';
116
- const s = "123";
117
- const ok = Result.unwrapOkOr(Num.safeParseInt(s), Number.NaN) > 5;
118
- `,
119
- errors: [{ messageId: 'useSafeParseInt' }],
199
+ errors: [
200
+ {
201
+ messageId: 'useSafeParseInt',
202
+ suggestions: [
203
+ {
204
+ messageId: 'replaceWithSafeParse',
205
+ output: dedent`
206
+ import { Num, Result } from 'ts-data-forge';
207
+ const s = "123";
208
+ const ok = Result.unwrapOkOr(Num.safeParseInt(s), Number.NaN) > 5;
209
+ `,
210
+ },
211
+ ],
212
+ },
213
+ ],
120
214
  },
121
215
  {
122
216
  name: 'preserves a complex string argument expression',
@@ -124,12 +218,21 @@ describe('prefer-num-safe-parse-int', () => {
124
218
  const get = (k: string): string => k;
125
219
  const n = parseInt(get("x").trim(), 10);
126
220
  `,
127
- output: dedent`
128
- import { Num, Result } from 'ts-data-forge';
129
- const get = (k: string): string => k;
130
- const n = Result.unwrapOkOr(Num.safeParseInt(get("x").trim()), Number.NaN);
131
- `,
132
- errors: [{ messageId: 'useSafeParseInt' }],
221
+ errors: [
222
+ {
223
+ messageId: 'useSafeParseInt',
224
+ suggestions: [
225
+ {
226
+ messageId: 'replaceWithSafeParse',
227
+ output: dedent`
228
+ import { Num, Result } from 'ts-data-forge';
229
+ const get = (k: string): string => k;
230
+ const n = Result.unwrapOkOr(Num.safeParseInt(get("x").trim()), Number.NaN);
231
+ `,
232
+ },
233
+ ],
234
+ },
235
+ ],
133
236
  },
134
237
  ],
135
238
  });
@@ -161,23 +264,35 @@ describe('prefer-num-safe-parse-int through type wrappers', () => {
161
264
  const a = parseInt(s, 10 as const);
162
265
  const b = Number.parseInt(s!, 10 satisfies number);
163
266
  `,
164
- output: [
165
- dedent`
166
- import { Num, Result } from 'ts-data-forge';
167
- declare const s: string;
168
- const a = Result.unwrapOkOr(Num.safeParseInt(s), Number.NaN);
169
- const b = Number.parseInt(s!, 10 satisfies number);
170
- `,
171
- dedent`
172
- import { Num, Result } from 'ts-data-forge';
173
- declare const s: string;
174
- const a = Result.unwrapOkOr(Num.safeParseInt(s), Number.NaN);
175
- const b = Result.unwrapOkOr(Num.safeParseInt(s!), Number.NaN);
176
- `,
177
- ],
178
267
  errors: [
179
- { messageId: 'useSafeParseInt' },
180
- { messageId: 'useSafeParseInt' },
268
+ {
269
+ messageId: 'useSafeParseInt',
270
+ suggestions: [
271
+ {
272
+ messageId: 'replaceWithSafeParse',
273
+ output: dedent`
274
+ import { Num, Result } from 'ts-data-forge';
275
+ declare const s: string;
276
+ const a = Result.unwrapOkOr(Num.safeParseInt(s), Number.NaN);
277
+ const b = Number.parseInt(s!, 10 satisfies number);
278
+ `,
279
+ },
280
+ ],
281
+ },
282
+ {
283
+ messageId: 'useSafeParseInt',
284
+ suggestions: [
285
+ {
286
+ messageId: 'replaceWithSafeParse',
287
+ output: dedent`
288
+ import { Num, Result } from 'ts-data-forge';
289
+ declare const s: string;
290
+ const a = parseInt(s, 10 as const);
291
+ const b = Result.unwrapOkOr(Num.safeParseInt(s!), Number.NaN);
292
+ `,
293
+ },
294
+ ],
295
+ },
181
296
  ],
182
297
  },
183
298
  {
@@ -187,23 +302,35 @@ describe('prefer-num-safe-parse-int through type wrappers', () => {
187
302
  const a = (parseInt as typeof parseInt)(s);
188
303
  const b = (Number as NumberConstructor)!.parseInt(s, 10);
189
304
  `,
190
- output: [
191
- dedent`
192
- import { Num, Result } from 'ts-data-forge';
193
- declare const s: string;
194
- const a = Result.unwrapOkOr(Num.safeParseInt(s), Number.NaN);
195
- const b = (Number as NumberConstructor)!.parseInt(s, 10);
196
- `,
197
- dedent`
198
- import { Num, Result } from 'ts-data-forge';
199
- declare const s: string;
200
- const a = Result.unwrapOkOr(Num.safeParseInt(s), Number.NaN);
201
- const b = Result.unwrapOkOr(Num.safeParseInt(s), Number.NaN);
202
- `,
203
- ],
204
305
  errors: [
205
- { messageId: 'useSafeParseInt' },
206
- { messageId: 'useSafeParseInt' },
306
+ {
307
+ messageId: 'useSafeParseInt',
308
+ suggestions: [
309
+ {
310
+ messageId: 'replaceWithSafeParse',
311
+ output: dedent`
312
+ import { Num, Result } from 'ts-data-forge';
313
+ declare const s: string;
314
+ const a = Result.unwrapOkOr(Num.safeParseInt(s), Number.NaN);
315
+ const b = (Number as NumberConstructor)!.parseInt(s, 10);
316
+ `,
317
+ },
318
+ ],
319
+ },
320
+ {
321
+ messageId: 'useSafeParseInt',
322
+ suggestions: [
323
+ {
324
+ messageId: 'replaceWithSafeParse',
325
+ output: dedent`
326
+ import { Num, Result } from 'ts-data-forge';
327
+ declare const s: string;
328
+ const a = (parseInt as typeof parseInt)(s);
329
+ const b = Result.unwrapOkOr(Num.safeParseInt(s), Number.NaN);
330
+ `,
331
+ },
332
+ ],
333
+ },
207
334
  ],
208
335
  },
209
336
  ],
@@ -221,13 +348,22 @@ describe('prefer-num-safe-parse-int with parenthesized operands', () => {
221
348
  declare const log: () => void;
222
349
  const a = parseInt((log(), s), 10);
223
350
  `,
224
- output: dedent`
225
- import { Num, Result } from 'ts-data-forge';
226
- declare const s: string;
227
- declare const log: () => void;
228
- const a = Result.unwrapOkOr(Num.safeParseInt((log(), s)), Number.NaN);
229
- `,
230
- errors: [{ messageId: 'useSafeParseInt' }],
351
+ errors: [
352
+ {
353
+ messageId: 'useSafeParseInt',
354
+ suggestions: [
355
+ {
356
+ messageId: 'replaceWithSafeParse',
357
+ output: dedent`
358
+ import { Num, Result } from 'ts-data-forge';
359
+ declare const s: string;
360
+ declare const log: () => void;
361
+ const a = Result.unwrapOkOr(Num.safeParseInt((log(), s)), Number.NaN);
362
+ `,
363
+ },
364
+ ],
365
+ },
366
+ ],
231
367
  },
232
368
  ],
233
369
  });