eslint-plugin-ts-data-forge 0.8.6 → 0.10.0

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 (70) hide show
  1. package/README.md +21 -19
  2. package/dist/plugin.d.mts +4 -0
  3. package/dist/plugin.d.mts.map +1 -1
  4. package/dist/plugin.mjs +2 -0
  5. package/dist/plugin.mjs.map +1 -1
  6. package/dist/rule-types.d.mts +31 -1
  7. package/dist/rule-types.d.mts.map +1 -1
  8. package/dist/rule-types.mjs.map +1 -1
  9. package/dist/rules/ast-utils.d.mts +21 -2
  10. package/dist/rules/ast-utils.d.mts.map +1 -1
  11. package/dist/rules/ast-utils.mjs +51 -4
  12. package/dist/rules/ast-utils.mjs.map +1 -1
  13. package/dist/rules/constants.d.mts +2 -0
  14. package/dist/rules/constants.d.mts.map +1 -1
  15. package/dist/rules/constants.mjs +9 -0
  16. package/dist/rules/constants.mjs.map +1 -1
  17. package/dist/rules/mutable-result.d.mts +10 -0
  18. package/dist/rules/mutable-result.d.mts.map +1 -0
  19. package/dist/rules/mutable-result.mjs +145 -0
  20. package/dist/rules/mutable-result.mjs.map +1 -0
  21. package/dist/rules/prefer-arr-generate.d.mts +57 -0
  22. package/dist/rules/prefer-arr-generate.d.mts.map +1 -0
  23. package/dist/rules/prefer-arr-generate.mjs +588 -0
  24. package/dist/rules/prefer-arr-generate.mjs.map +1 -0
  25. package/dist/rules/prefer-arr-uniq.d.mts.map +1 -1
  26. package/dist/rules/prefer-arr-uniq.mjs +2 -149
  27. package/dist/rules/prefer-arr-uniq.mjs.map +1 -1
  28. package/dist/rules/prefer-canonical-array-slicing.d.mts.map +1 -1
  29. package/dist/rules/prefer-canonical-array-slicing.mjs +47 -28
  30. package/dist/rules/prefer-canonical-array-slicing.mjs.map +1 -1
  31. package/dist/rules/prefer-is-non-null-object.d.mts.map +1 -1
  32. package/dist/rules/prefer-is-non-null-object.mjs +110 -40
  33. package/dist/rules/prefer-is-non-null-object.mjs.map +1 -1
  34. package/dist/rules/prefer-is-record-and-has-key.d.mts.map +1 -1
  35. package/dist/rules/prefer-is-record-and-has-key.mjs +102 -45
  36. package/dist/rules/prefer-is-record-and-has-key.mjs.map +1 -1
  37. package/dist/rules/prefer-pipe-map-nullable.d.mts +24 -0
  38. package/dist/rules/prefer-pipe-map-nullable.d.mts.map +1 -0
  39. package/dist/rules/prefer-pipe-map-nullable.mjs +266 -0
  40. package/dist/rules/prefer-pipe-map-nullable.mjs.map +1 -0
  41. package/dist/rules/prefer-range-for-loop.d.mts.map +1 -1
  42. package/dist/rules/prefer-range-for-loop.mjs +97 -16
  43. package/dist/rules/prefer-range-for-loop.mjs.map +1 -1
  44. package/dist/rules/rules.d.mts +2 -0
  45. package/dist/rules/rules.d.mts.map +1 -1
  46. package/dist/rules/rules.mjs +4 -0
  47. package/dist/rules/rules.mjs.map +1 -1
  48. package/package.json +11 -11
  49. package/src/plugin.mts +2 -0
  50. package/src/rule-types.mts +33 -1
  51. package/src/rules/ast-utils.mts +72 -5
  52. package/src/rules/constants.mts +12 -0
  53. package/src/rules/mutable-result.mts +204 -0
  54. package/src/rules/prefer-arr-generate.mts +918 -0
  55. package/src/rules/prefer-arr-generate.test.mts +967 -0
  56. package/src/rules/prefer-arr-is-bounded-length-array.test.mts +19 -0
  57. package/src/rules/prefer-arr-is-max-length-array.test.mts +8 -0
  58. package/src/rules/prefer-arr-is-min-length-array.test.mts +8 -0
  59. package/src/rules/prefer-arr-uniq.mts +2 -207
  60. package/src/rules/prefer-canonical-array-slicing.mts +57 -40
  61. package/src/rules/prefer-canonical-array-slicing.test.mts +55 -0
  62. package/src/rules/prefer-is-non-null-object.mts +160 -57
  63. package/src/rules/prefer-is-non-null-object.test.mts +138 -0
  64. package/src/rules/prefer-is-record-and-has-key.mts +148 -67
  65. package/src/rules/prefer-is-record-and-has-key.test.mts +118 -23
  66. package/src/rules/prefer-pipe-map-nullable.mts +391 -0
  67. package/src/rules/prefer-pipe-map-nullable.test.mts +470 -0
  68. package/src/rules/prefer-range-for-loop.mts +142 -21
  69. package/src/rules/prefer-range-for-loop.test.mts +127 -5
  70. package/src/rules/rules.mts +4 -0
@@ -205,22 +205,20 @@ describe('prefer-range-for-loop with parenthesized operands', () => {
205
205
  valid: [],
206
206
  invalid: [
207
207
  {
208
- name: 'sequence bounds and step keep their parentheses',
208
+ name: 'a sequence begin keeps its parentheses',
209
209
  code: dedent`
210
210
  import { range } from 'ts-data-forge';
211
211
  declare const n: number;
212
- declare const step: number;
213
212
  declare const log: () => void;
214
- for (let i = (log(), 0); i < (log(), n); i += (log(), step)) {
213
+ for (let i = (log(), 0); i < n; ++i) {
215
214
  console.log(i);
216
215
  }
217
216
  `,
218
217
  output: dedent`
219
218
  import { range } from 'ts-data-forge';
220
219
  declare const n: number;
221
- declare const step: number;
222
220
  declare const log: () => void;
223
- for (const i of range((log(), 0), (log(), n), (log(), step))) {
221
+ for (const i of range((log(), 0), n)) {
224
222
  console.log(i);
225
223
  }
226
224
  `,
@@ -229,3 +227,127 @@ describe('prefer-range-for-loop with parenthesized operands', () => {
229
227
  ],
230
228
  });
231
229
  }, 20000);
230
+
231
+ describe('prefer-range-for-loop where the rewrite would change behavior', () => {
232
+ tester.run('prefer-range-for-loop', preferRangeForLoop, {
233
+ valid: [
234
+ {
235
+ // `const i` could not be assigned.
236
+ name: 'the loop variable assigned in the body',
237
+ code: dedent`
238
+ declare const n: number;
239
+ declare const skip: boolean;
240
+ for (let i = 0; i < n; ++i) {
241
+ if (skip) i += 1;
242
+ }
243
+ for (let j = 0; j < n; ++j) {
244
+ j = n;
245
+ }
246
+ `,
247
+ },
248
+ {
249
+ // `range` takes safe integers only.
250
+ name: 'a step or a begin that is not an integer',
251
+ code: dedent`
252
+ declare const n: number;
253
+ for (let i = 0; i < n; i += 0.5) {
254
+ console.log(i);
255
+ }
256
+ for (let j = 0.5; j < n; ++j) {
257
+ console.log(j);
258
+ }
259
+ `,
260
+ },
261
+ {
262
+ // `i < n` with a negative step never ends; `range` yields nothing.
263
+ name: 'a negative literal step',
264
+ code: dedent`
265
+ declare const n: number;
266
+ for (let i = 0; i < n; i += -1) {
267
+ console.log(i);
268
+ }
269
+ `,
270
+ },
271
+ ],
272
+ invalid: [
273
+ {
274
+ // The loop tests its end on every iteration; `range` reads it once.
275
+ name: 'an end that is not a literal or a never-reassigned variable gets no fix',
276
+ code: dedent`
277
+ declare const xs: number[];
278
+ declare const getN: () => number;
279
+ let m = 3;
280
+ for (let i = 0; i < xs.length; ++i) {
281
+ xs.pop();
282
+ }
283
+ for (let j = 0; j < getN(); ++j) {
284
+ console.log(j);
285
+ }
286
+ for (let k = 0; k < m; ++k) {
287
+ m -= 1;
288
+ }
289
+ `,
290
+ output: null,
291
+ errors: [
292
+ { messageId: 'useRangeForLoop' },
293
+ { messageId: 'useRangeForLoop' },
294
+ { messageId: 'useRangeForLoop' },
295
+ ],
296
+ },
297
+ {
298
+ // The loop adds the step it reads on each iteration; `range` reads it
299
+ // once.
300
+ name: 'a variable step that is reassigned gets no fix',
301
+ code: dedent`
302
+ declare const n: number;
303
+ let step = 1;
304
+ for (let i = 0; i < n; i += step) {
305
+ step *= 2;
306
+ }
307
+ `,
308
+ output: null,
309
+ errors: [{ messageId: 'useRangeForLoop' }],
310
+ },
311
+ {
312
+ // The type checker judges it: a `number` step makes the fixed call
313
+ // fail to type-check.
314
+ name: 'a variable step is fixed without asking its type',
315
+ code: dedent`
316
+ declare const n: number;
317
+ declare const step: number;
318
+ for (let i = 0; i < n; i += step) {
319
+ console.log(i);
320
+ }
321
+ `,
322
+ output: dedent`
323
+ import { range } from 'ts-data-forge';
324
+ declare const n: number;
325
+ declare const step: number;
326
+ for (const i of range(0, n, step)) {
327
+ console.log(i);
328
+ }
329
+ `,
330
+ errors: [{ messageId: 'useRangeForLoop' }],
331
+ },
332
+ {
333
+ name: 'a parameter that is never reassigned is a fixed end',
334
+ code: dedent`
335
+ const f = (n: number): void => {
336
+ for (let i = 0; i < n; ++i) {
337
+ console.log(i);
338
+ }
339
+ };
340
+ `,
341
+ output: dedent`
342
+ import { range } from 'ts-data-forge';
343
+ const f = (n: number): void => {
344
+ for (const i of range(0, n)) {
345
+ console.log(i);
346
+ }
347
+ };
348
+ `,
349
+ errors: [{ messageId: 'useRangeForLoop' }],
350
+ },
351
+ ],
352
+ });
353
+ }, 20000);
@@ -1,6 +1,7 @@
1
1
  import type { ESLintPlugin } from '../types.mjs';
2
2
  import { noSideEffectImport } from './no-side-effect-import.mjs';
3
3
  import { noUnnecessaryTypeGuard } from './no-unnecessary-type-guard.mjs';
4
+ import { preferArrGenerate } from './prefer-arr-generate.mjs';
4
5
  import { preferArrIsArray } from './prefer-arr-is-array.mjs';
5
6
  import { preferArrScan } from './prefer-arr-scan.mjs';
6
7
  import { preferArrSum } from './prefer-arr-sum.mjs';
@@ -15,12 +16,14 @@ import { preferIsRecordAndHasKey } from './prefer-is-record-and-has-key.mjs';
15
16
  import { preferNumSafeParseFloat } from './prefer-num-safe-parse-float.mjs';
16
17
  import { preferNumSafeParseInt } from './prefer-num-safe-parse-int.mjs';
17
18
  import { preferObjOverEntriesRoundTrip } from './prefer-obj-over-entries-round-trip.mjs';
19
+ import { preferPipeMapNullable } from './prefer-pipe-map-nullable.mjs';
18
20
  import { preferRangeForLoop } from './prefer-range-for-loop.mjs';
19
21
 
20
22
  export const tsDataForgeRules = {
21
23
  'prefer-canonical-array-slicing': preferCanonicalArraySlicing,
22
24
  'prefer-canonical-length-guard': preferCanonicalLengthGuard,
23
25
  'prefer-canonical-length-cast': preferCanonicalLengthCast,
26
+ 'prefer-arr-generate': preferArrGenerate,
24
27
  'prefer-arr-is-array': preferArrIsArray,
25
28
  'prefer-arr-scan': preferArrScan,
26
29
  'prefer-arr-sum': preferArrSum,
@@ -35,4 +38,5 @@ export const tsDataForgeRules = {
35
38
  'no-unnecessary-type-guard': noUnnecessaryTypeGuard,
36
39
  'prefer-comparison-over-nullish-guard': preferComparisonOverNullishGuard,
37
40
  'prefer-obj-over-entries-round-trip': preferObjOverEntriesRoundTrip,
41
+ 'prefer-pipe-map-nullable': preferPipeMapNullable,
38
42
  } as const satisfies ESLintPlugin['rules'];