eslint-plugin-ts-data-forge 0.8.2 → 0.8.3

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 (132) hide show
  1. package/dist/plugin.d.mts +1 -1
  2. package/dist/plugin.d.mts.map +1 -1
  3. package/dist/plugin.mjs +1 -0
  4. package/dist/plugin.mjs.map +1 -1
  5. package/dist/rule-types.d.mts +3 -3
  6. package/dist/rule-types.d.mts.map +1 -1
  7. package/dist/rules/ast-utils.d.mts +59 -3
  8. package/dist/rules/ast-utils.d.mts.map +1 -1
  9. package/dist/rules/ast-utils.mjs +119 -8
  10. package/dist/rules/ast-utils.mjs.map +1 -1
  11. package/dist/rules/import-utils.d.mts +1 -1
  12. package/dist/rules/import-utils.d.mts.map +1 -1
  13. package/dist/rules/import-utils.mjs +22 -11
  14. package/dist/rules/import-utils.mjs.map +1 -1
  15. package/dist/rules/no-side-effect-import.d.mts +1 -1
  16. package/dist/rules/no-side-effect-import.d.mts.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 +125 -79
  19. package/dist/rules/no-unnecessary-type-guard.mjs.map +1 -1
  20. package/dist/rules/prefer-arr-is-array.mjs +11 -4
  21. package/dist/rules/prefer-arr-is-array.mjs.map +1 -1
  22. package/dist/rules/prefer-arr-is-bounded-length-array.d.mts +1 -1
  23. package/dist/rules/prefer-arr-is-bounded-length-array.d.mts.map +1 -1
  24. package/dist/rules/prefer-arr-is-bounded-length-array.mjs +5 -19
  25. package/dist/rules/prefer-arr-is-bounded-length-array.mjs.map +1 -1
  26. package/dist/rules/prefer-arr-is-fixed-length-array.d.mts +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 +11 -27
  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 +1 -1
  31. package/dist/rules/prefer-arr-is-max-length-array.d.mts.map +1 -1
  32. package/dist/rules/prefer-arr-is-max-length-array.mjs +9 -22
  33. package/dist/rules/prefer-arr-is-max-length-array.mjs.map +1 -1
  34. package/dist/rules/prefer-arr-is-min-length-array.d.mts +1 -1
  35. package/dist/rules/prefer-arr-is-min-length-array.d.mts.map +1 -1
  36. package/dist/rules/prefer-arr-is-min-length-array.mjs +9 -22
  37. package/dist/rules/prefer-arr-is-min-length-array.mjs.map +1 -1
  38. package/dist/rules/prefer-arr-is-non-empty.d.mts.map +1 -1
  39. package/dist/rules/prefer-arr-is-non-empty.mjs +7 -22
  40. package/dist/rules/prefer-arr-is-non-empty.mjs.map +1 -1
  41. package/dist/rules/prefer-arr-scan.d.mts +6 -5
  42. package/dist/rules/prefer-arr-scan.d.mts.map +1 -1
  43. package/dist/rules/prefer-arr-scan.mjs +33 -13
  44. package/dist/rules/prefer-arr-scan.mjs.map +1 -1
  45. package/dist/rules/prefer-arr-sum.d.mts.map +1 -1
  46. package/dist/rules/prefer-arr-sum.mjs +51 -37
  47. package/dist/rules/prefer-arr-sum.mjs.map +1 -1
  48. package/dist/rules/prefer-arr-uniq.d.mts.map +1 -1
  49. package/dist/rules/prefer-arr-uniq.mjs +33 -10
  50. package/dist/rules/prefer-arr-uniq.mjs.map +1 -1
  51. package/dist/rules/prefer-as-int.d.mts.map +1 -1
  52. package/dist/rules/prefer-as-int.mjs +18 -12
  53. package/dist/rules/prefer-as-int.mjs.map +1 -1
  54. package/dist/rules/prefer-canonical-array-slicing.d.mts.map +1 -1
  55. package/dist/rules/prefer-canonical-array-slicing.mjs +29 -14
  56. package/dist/rules/prefer-canonical-array-slicing.mjs.map +1 -1
  57. package/dist/rules/prefer-canonical-length-cast.d.mts.map +1 -1
  58. package/dist/rules/prefer-canonical-length-cast.mjs +34 -13
  59. package/dist/rules/prefer-canonical-length-cast.mjs.map +1 -1
  60. package/dist/rules/prefer-canonical-length-guard.d.mts.map +1 -1
  61. package/dist/rules/prefer-canonical-length-guard.mjs +10 -4
  62. package/dist/rules/prefer-canonical-length-guard.mjs.map +1 -1
  63. package/dist/rules/prefer-comparison-over-nullish-guard.d.mts.map +1 -1
  64. package/dist/rules/prefer-comparison-over-nullish-guard.mjs +25 -3
  65. package/dist/rules/prefer-comparison-over-nullish-guard.mjs.map +1 -1
  66. package/dist/rules/prefer-is-non-null-object.mjs +28 -10
  67. package/dist/rules/prefer-is-non-null-object.mjs.map +1 -1
  68. package/dist/rules/prefer-is-record-and-has-key.d.mts.map +1 -1
  69. package/dist/rules/prefer-is-record-and-has-key.mjs +8 -3
  70. package/dist/rules/prefer-is-record-and-has-key.mjs.map +1 -1
  71. package/dist/rules/prefer-num-safe-parse-float.d.mts +3 -1
  72. package/dist/rules/prefer-num-safe-parse-float.d.mts.map +1 -1
  73. package/dist/rules/prefer-num-safe-parse-float.mjs +18 -7
  74. package/dist/rules/prefer-num-safe-parse-float.mjs.map +1 -1
  75. package/dist/rules/prefer-num-safe-parse-int.d.mts.map +1 -1
  76. package/dist/rules/prefer-num-safe-parse-int.mjs +15 -8
  77. package/dist/rules/prefer-num-safe-parse-int.mjs.map +1 -1
  78. package/dist/rules/prefer-range-for-loop.d.mts.map +1 -1
  79. package/dist/rules/prefer-range-for-loop.mjs +13 -7
  80. package/dist/rules/prefer-range-for-loop.mjs.map +1 -1
  81. package/dist/types.d.mts +2 -2
  82. package/dist/types.d.mts.map +1 -1
  83. package/package.json +3 -3
  84. package/src/plugin.mts +5 -4
  85. package/src/plugin.test.mts +0 -13
  86. package/src/rule-types.mts +3 -3
  87. package/src/rules/ast-utils.mts +156 -13
  88. package/src/rules/import-utils.mts +35 -15
  89. package/src/rules/no-side-effect-import.mts +1 -1
  90. package/src/rules/no-unnecessary-type-guard.mts +192 -124
  91. package/src/rules/no-unnecessary-type-guard.test.mts +100 -0
  92. package/src/rules/prefer-arr-is-array.mts +11 -6
  93. package/src/rules/prefer-arr-is-array.test.mts +40 -0
  94. package/src/rules/prefer-arr-is-bounded-length-array.mts +13 -25
  95. package/src/rules/prefer-arr-is-bounded-length-array.test.mts +68 -0
  96. package/src/rules/prefer-arr-is-fixed-length-array.mts +18 -38
  97. package/src/rules/prefer-arr-is-fixed-length-array.test.mts +63 -0
  98. package/src/rules/prefer-arr-is-max-length-array.mts +15 -26
  99. package/src/rules/prefer-arr-is-max-length-array.test.mts +67 -0
  100. package/src/rules/prefer-arr-is-min-length-array.mts +15 -26
  101. package/src/rules/prefer-arr-is-min-length-array.test.mts +70 -0
  102. package/src/rules/prefer-arr-is-non-empty.mts +16 -25
  103. package/src/rules/prefer-arr-is-non-empty.test.mts +79 -0
  104. package/src/rules/prefer-arr-scan.mts +55 -19
  105. package/src/rules/prefer-arr-scan.test.mts +149 -0
  106. package/src/rules/prefer-arr-sum.mts +78 -47
  107. package/src/rules/prefer-arr-sum.test.mts +97 -0
  108. package/src/rules/prefer-arr-uniq.mts +46 -12
  109. package/src/rules/prefer-arr-uniq.test.mts +71 -0
  110. package/src/rules/prefer-as-int.mts +24 -16
  111. package/src/rules/prefer-as-int.test.mts +51 -0
  112. package/src/rules/prefer-canonical-array-slicing.mts +38 -15
  113. package/src/rules/prefer-canonical-array-slicing.test.mts +92 -0
  114. package/src/rules/prefer-canonical-length-cast.mts +45 -15
  115. package/src/rules/prefer-canonical-length-cast.test.mts +111 -0
  116. package/src/rules/prefer-canonical-length-guard.mts +13 -7
  117. package/src/rules/prefer-canonical-length-guard.test.mts +99 -0
  118. package/src/rules/prefer-comparison-over-nullish-guard.mts +33 -6
  119. package/src/rules/prefer-comparison-over-nullish-guard.test.mts +136 -0
  120. package/src/rules/prefer-is-non-null-object.mts +31 -11
  121. package/src/rules/prefer-is-non-null-object.test.mts +42 -0
  122. package/src/rules/prefer-is-record-and-has-key.mts +10 -5
  123. package/src/rules/prefer-is-record-and-has-key.test.mts +34 -0
  124. package/src/rules/prefer-num-safe-parse-float.mts +24 -11
  125. package/src/rules/prefer-num-safe-parse-float.test.mts +79 -0
  126. package/src/rules/prefer-num-safe-parse-int.mts +25 -11
  127. package/src/rules/prefer-num-safe-parse-int.test.mts +64 -0
  128. package/src/rules/prefer-obj-over-entries-round-trip.mts +1 -1
  129. package/src/rules/prefer-range-for-loop.mts +18 -8
  130. package/src/rules/prefer-range-for-loop.test.mts +75 -0
  131. package/src/rules/rules.mts +1 -1
  132. package/src/types.mts +2 -2
@@ -4,6 +4,7 @@ import {
4
4
  type TSESTree,
5
5
  } from '@typescript-eslint/utils';
6
6
  import { Arr } from 'ts-data-forge';
7
+ import { skipTypeWrappers, toArgumentText } from './ast-utils.mjs';
7
8
  import {
8
9
  buildImportFixes,
9
10
  getNamedImports,
@@ -68,12 +69,21 @@ export const preferRangeForLoop: TSESLint.RuleModule<MessageIds, Options> = {
68
69
 
69
70
  const beginExpr = declaration.init;
70
71
 
71
- // Check test: i < end
72
+ // Check test: i < end. The loop variable and the step are read
73
+ // through type wrappers: `(i satisfies number) < n` tests `i`, and
74
+ // `i += 0 as number` still steps by 0.
72
75
  if (
73
76
  node.test?.type !== AST_NODE_TYPES.BinaryExpression ||
74
- node.test.operator !== '<' ||
75
- node.test.left.type !== AST_NODE_TYPES.Identifier ||
76
- node.test.left.name !== varName
77
+ node.test.operator !== '<'
78
+ ) {
79
+ return;
80
+ }
81
+
82
+ const testedVariable = skipTypeWrappers(node.test.left);
83
+
84
+ if (
85
+ testedVariable.type !== AST_NODE_TYPES.Identifier ||
86
+ testedVariable.name !== varName
77
87
  ) {
78
88
  return;
79
89
  }
@@ -105,7 +115,7 @@ export const preferRangeForLoop: TSESLint.RuleModule<MessageIds, Options> = {
105
115
  node.update.left.name === varName
106
116
  ) {
107
117
  // i += step
108
- const stepValue = node.update.right;
118
+ const stepValue = skipTypeWrappers(node.update.right);
109
119
 
110
120
  if (stepValue.type === AST_NODE_TYPES.Literal) {
111
121
  const stepNum = stepValue.value;
@@ -118,15 +128,15 @@ export const preferRangeForLoop: TSESLint.RuleModule<MessageIds, Options> = {
118
128
  }
119
129
  } else {
120
130
  // Variable step like i += step
121
- mut_step = sourceCode.getText(stepValue);
131
+ mut_step = toArgumentText(node.update.right, sourceCode);
122
132
  }
123
133
  } else {
124
134
  return;
125
135
  }
126
136
 
127
- const beginText = sourceCode.getText(beginExpr);
137
+ const beginText = toArgumentText(beginExpr, sourceCode);
128
138
 
129
- const endText = sourceCode.getText(endExpr);
139
+ const endText = toArgumentText(endExpr, sourceCode);
130
140
 
131
141
  mut_nodesToFix.push({
132
142
  node,
@@ -154,3 +154,78 @@ describe('prefer-range-for-loop', () => {
154
154
  ],
155
155
  });
156
156
  }, 20000);
157
+
158
+ describe('prefer-range-for-loop through type wrappers', () => {
159
+ tester.run('prefer-range-for-loop', preferRangeForLoop, {
160
+ valid: [
161
+ {
162
+ name: 'a wrapped non-positive step',
163
+ code: dedent`
164
+ declare const n: number;
165
+ for (let i = 0; i < n; i += 0 as number) {
166
+ console.log(i);
167
+ }
168
+ `,
169
+ },
170
+ ],
171
+ invalid: [
172
+ {
173
+ name: 'the loop variable or the step wrapped',
174
+ code: dedent`
175
+ import { range } from 'ts-data-forge';
176
+ declare const n: number;
177
+ for (let i = 0; (i satisfies number) < n; ++i) {
178
+ console.log(i);
179
+ }
180
+ for (let j = 0; j! < n; j += 2 as number) {
181
+ console.log(j);
182
+ }
183
+ `,
184
+ output: dedent`
185
+ import { range } from 'ts-data-forge';
186
+ declare const n: number;
187
+ for (const i of range(0, n)) {
188
+ console.log(i);
189
+ }
190
+ for (const j of range(0, n, 2)) {
191
+ console.log(j);
192
+ }
193
+ `,
194
+ errors: [
195
+ { messageId: 'useRangeForLoop' },
196
+ { messageId: 'useRangeForLoop' },
197
+ ],
198
+ },
199
+ ],
200
+ });
201
+ }, 20000);
202
+
203
+ describe('prefer-range-for-loop with parenthesized operands', () => {
204
+ tester.run('prefer-range-for-loop', preferRangeForLoop, {
205
+ valid: [],
206
+ invalid: [
207
+ {
208
+ name: 'sequence bounds and step keep their parentheses',
209
+ code: dedent`
210
+ import { range } from 'ts-data-forge';
211
+ declare const n: number;
212
+ declare const step: number;
213
+ declare const log: () => void;
214
+ for (let i = (log(), 0); i < (log(), n); i += (log(), step)) {
215
+ console.log(i);
216
+ }
217
+ `,
218
+ output: dedent`
219
+ import { range } from 'ts-data-forge';
220
+ declare const n: number;
221
+ declare const step: number;
222
+ declare const log: () => void;
223
+ for (const i of range((log(), 0), (log(), n), (log(), step))) {
224
+ console.log(i);
225
+ }
226
+ `,
227
+ errors: [{ messageId: 'useRangeForLoop' }],
228
+ },
229
+ ],
230
+ });
231
+ }, 20000);
@@ -1,4 +1,4 @@
1
- import { type ESLintPlugin } from '../types.mjs';
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
4
  import { preferArrIsArray } from './prefer-arr-is-array.mjs';
package/src/types.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { type TSESLint } from '@typescript-eslint/utils';
2
- import { type DeepReadonly } from 'ts-type-forge';
1
+ import type { TSESLint } from '@typescript-eslint/utils';
2
+ import type { DeepReadonly } from 'ts-type-forge';
3
3
 
4
4
  export type ESLintPlugin = DeepReadonly<TSESLint.FlatConfig.Plugin>;
5
5