eslint-plugin-ts-data-forge 0.1.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.
- package/LICENSE +201 -0
- package/README.md +57 -0
- package/package.json +74 -0
- package/src/index.mts +7 -0
- package/src/plugin.mts +9 -0
- package/src/rule-types.mts +326 -0
- package/src/rules/ast-utils.mts +169 -0
- package/src/rules/branded-number-types.mts +47 -0
- package/src/rules/constants.mts +1 -0
- package/src/rules/import-utils.mts +152 -0
- package/src/rules/index.mts +1 -0
- package/src/rules/no-unnecessary-type-guard.mts +515 -0
- package/src/rules/no-unnecessary-type-guard.test.mts +368 -0
- package/src/rules/prefer-arr-is-array.mts +98 -0
- package/src/rules/prefer-arr-is-array.test.mts +62 -0
- package/src/rules/prefer-arr-is-bounded-length-array.mts +143 -0
- package/src/rules/prefer-arr-is-bounded-length-array.test.mts +154 -0
- package/src/rules/prefer-arr-is-fixed-length-array.mts +149 -0
- package/src/rules/prefer-arr-is-fixed-length-array.test.mts +214 -0
- package/src/rules/prefer-arr-is-max-length-array.mts +141 -0
- package/src/rules/prefer-arr-is-max-length-array.test.mts +188 -0
- package/src/rules/prefer-arr-is-min-length-array.mts +141 -0
- package/src/rules/prefer-arr-is-min-length-array.test.mts +202 -0
- package/src/rules/prefer-arr-is-non-empty.mts +131 -0
- package/src/rules/prefer-arr-is-non-empty.test.mts +90 -0
- package/src/rules/prefer-arr-sum.mts +269 -0
- package/src/rules/prefer-arr-sum.test.mts +171 -0
- package/src/rules/prefer-as-int.mts +131 -0
- package/src/rules/prefer-as-int.test.mts +267 -0
- package/src/rules/prefer-canonical-array-slicing.mts +800 -0
- package/src/rules/prefer-canonical-array-slicing.test.mts +588 -0
- package/src/rules/prefer-comparison-over-nullish-guard.mts +141 -0
- package/src/rules/prefer-comparison-over-nullish-guard.test.mts +171 -0
- package/src/rules/prefer-is-non-null-object.mts +145 -0
- package/src/rules/prefer-is-non-null-object.test.mts +156 -0
- package/src/rules/prefer-is-record-and-has-key.mts +156 -0
- package/src/rules/prefer-is-record-and-has-key.test.mts +217 -0
- package/src/rules/prefer-num-safe-parse-float.mts +166 -0
- package/src/rules/prefer-num-safe-parse-float.test.mts +163 -0
- package/src/rules/prefer-num-safe-parse-int.mts +166 -0
- package/src/rules/prefer-num-safe-parse-int.test.mts +137 -0
- package/src/rules/prefer-range-for-loop.mts +179 -0
- package/src/rules/prefer-range-for-loop.test.mts +156 -0
- package/src/rules/rules.mts +36 -0
- package/src/types.mts +4 -0
|
@@ -0,0 +1,588 @@
|
|
|
1
|
+
import parser from '@typescript-eslint/parser';
|
|
2
|
+
import { RuleTester } from '@typescript-eslint/rule-tester';
|
|
3
|
+
import dedent from 'dedent';
|
|
4
|
+
import { preferCanonicalArraySlicing } from './prefer-canonical-array-slicing.mjs';
|
|
5
|
+
|
|
6
|
+
const tester = new RuleTester({
|
|
7
|
+
languageOptions: {
|
|
8
|
+
parser,
|
|
9
|
+
parserOptions: {
|
|
10
|
+
ecmaVersion: 2020,
|
|
11
|
+
sourceType: 'module',
|
|
12
|
+
projectService: {
|
|
13
|
+
allowDefaultProject: ['*.ts*'],
|
|
14
|
+
},
|
|
15
|
+
tsconfigRootDir: `${import.meta.dirname}/../..`,
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
describe('prefer-canonical-array-slicing', () => {
|
|
21
|
+
tester.run('prefer-canonical-array-slicing', preferCanonicalArraySlicing, {
|
|
22
|
+
valid: [
|
|
23
|
+
{
|
|
24
|
+
name: 'full copy via slice() is out of scope',
|
|
25
|
+
code: dedent`
|
|
26
|
+
declare const xs: readonly number[];
|
|
27
|
+
const ys = xs.slice();
|
|
28
|
+
`,
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
name: 'full copy via slice(0) is out of scope',
|
|
32
|
+
code: dedent`
|
|
33
|
+
declare const xs: readonly number[];
|
|
34
|
+
const ys = xs.slice(0);
|
|
35
|
+
`,
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
name: 'slice with a non-literal count is left untouched',
|
|
39
|
+
code: dedent`
|
|
40
|
+
declare const xs: readonly number[];
|
|
41
|
+
declare const n: number;
|
|
42
|
+
const ys = xs.slice(n);
|
|
43
|
+
`,
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
name: 'slice on a string is not an array operation',
|
|
47
|
+
code: dedent`
|
|
48
|
+
declare const s: string;
|
|
49
|
+
const t = s.slice(1);
|
|
50
|
+
`,
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
name: 'value-based filter is left untouched',
|
|
54
|
+
code: dedent`
|
|
55
|
+
declare const xs: readonly number[];
|
|
56
|
+
const ys = xs.filter((v) => v > 0);
|
|
57
|
+
`,
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
name: 'filter whose element param shadows the receiver is skipped',
|
|
61
|
+
code: dedent`
|
|
62
|
+
declare const xs: readonly (readonly number[])[];
|
|
63
|
+
const ys = xs.filter((xs, i) => i < xs.length - 1);
|
|
64
|
+
`,
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
name: 'concat with an array argument flattens, not appends',
|
|
68
|
+
code: dedent`
|
|
69
|
+
declare const xs: readonly number[];
|
|
70
|
+
declare const ys: readonly number[];
|
|
71
|
+
const zs = xs.concat(ys);
|
|
72
|
+
`,
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
name: 'toSpliced(0, -N) clamps the delete count and is a plain copy',
|
|
76
|
+
code: dedent`
|
|
77
|
+
declare const xs: readonly number[];
|
|
78
|
+
const ys = xs.toSpliced(0, -2);
|
|
79
|
+
`,
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
name: 'Arr.skip with a count other than 1 is already canonical',
|
|
83
|
+
code: dedent`
|
|
84
|
+
import { Arr } from 'ts-data-forge';
|
|
85
|
+
declare const xs: readonly number[];
|
|
86
|
+
const ys = Arr.skip(xs, 2);
|
|
87
|
+
`,
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
name: 'receiver with side effects is not referenced twice',
|
|
91
|
+
code: dedent`
|
|
92
|
+
declare const getXs: () => readonly number[];
|
|
93
|
+
const ys = getXs().filter((_, i) => i < getXs().length - 1);
|
|
94
|
+
`,
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
name: 'spreading a Set is a genuine conversion, not element addition',
|
|
98
|
+
code: dedent`
|
|
99
|
+
declare const xs: Set<number>;
|
|
100
|
+
const ys = [...xs, 0];
|
|
101
|
+
`,
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
name: 'two-element array literal without spread is out of scope',
|
|
105
|
+
code: dedent`
|
|
106
|
+
declare const a: number;
|
|
107
|
+
declare const b: number;
|
|
108
|
+
const ys = [a, b];
|
|
109
|
+
`,
|
|
110
|
+
},
|
|
111
|
+
],
|
|
112
|
+
invalid: [
|
|
113
|
+
// ---- tail ----
|
|
114
|
+
{
|
|
115
|
+
name: 'xs.toSpliced(0, 1) → Arr.tail(xs)',
|
|
116
|
+
code: dedent`
|
|
117
|
+
declare const xs: readonly number[];
|
|
118
|
+
const ys = xs.toSpliced(0, 1);
|
|
119
|
+
`,
|
|
120
|
+
output: dedent`
|
|
121
|
+
import { Arr } from 'ts-data-forge';
|
|
122
|
+
declare const xs: readonly number[];
|
|
123
|
+
const ys = Arr.tail(xs);
|
|
124
|
+
`,
|
|
125
|
+
errors: [{ messageId: 'preferCanonicalArraySlicing' }],
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
name: 'xs.slice(1) → Arr.tail(xs)',
|
|
129
|
+
code: dedent`
|
|
130
|
+
declare const xs: readonly number[];
|
|
131
|
+
const ys = xs.slice(1);
|
|
132
|
+
`,
|
|
133
|
+
output: dedent`
|
|
134
|
+
import { Arr } from 'ts-data-forge';
|
|
135
|
+
declare const xs: readonly number[];
|
|
136
|
+
const ys = Arr.tail(xs);
|
|
137
|
+
`,
|
|
138
|
+
errors: [{ messageId: 'preferCanonicalArraySlicing' }],
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
name: 'xs.filter((_, i) => i >= 1) → Arr.tail(xs)',
|
|
142
|
+
code: dedent`
|
|
143
|
+
declare const xs: readonly number[];
|
|
144
|
+
const ys = xs.filter((_, i) => i >= 1);
|
|
145
|
+
`,
|
|
146
|
+
output: dedent`
|
|
147
|
+
import { Arr } from 'ts-data-forge';
|
|
148
|
+
declare const xs: readonly number[];
|
|
149
|
+
const ys = Arr.tail(xs);
|
|
150
|
+
`,
|
|
151
|
+
errors: [{ messageId: 'preferCanonicalArraySlicing' }],
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
name: 'xs.filter((_, i) => i > 0) → Arr.tail(xs)',
|
|
155
|
+
code: dedent`
|
|
156
|
+
declare const xs: readonly number[];
|
|
157
|
+
const ys = xs.filter((_, i) => i > 0);
|
|
158
|
+
`,
|
|
159
|
+
output: dedent`
|
|
160
|
+
import { Arr } from 'ts-data-forge';
|
|
161
|
+
declare const xs: readonly number[];
|
|
162
|
+
const ys = Arr.tail(xs);
|
|
163
|
+
`,
|
|
164
|
+
errors: [{ messageId: 'preferCanonicalArraySlicing' }],
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
name: 'xs.filter((_, i) => i !== 0) → Arr.tail(xs)',
|
|
168
|
+
code: dedent`
|
|
169
|
+
declare const xs: readonly number[];
|
|
170
|
+
const ys = xs.filter((_, i) => i !== 0);
|
|
171
|
+
`,
|
|
172
|
+
output: dedent`
|
|
173
|
+
import { Arr } from 'ts-data-forge';
|
|
174
|
+
declare const xs: readonly number[];
|
|
175
|
+
const ys = Arr.tail(xs);
|
|
176
|
+
`,
|
|
177
|
+
errors: [{ messageId: 'preferCanonicalArraySlicing' }],
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
name: 'flipped operand order (0 < i) is also recognized',
|
|
181
|
+
code: dedent`
|
|
182
|
+
declare const xs: readonly number[];
|
|
183
|
+
const ys = xs.filter((_, i) => 0 < i);
|
|
184
|
+
`,
|
|
185
|
+
output: dedent`
|
|
186
|
+
import { Arr } from 'ts-data-forge';
|
|
187
|
+
declare const xs: readonly number[];
|
|
188
|
+
const ys = Arr.tail(xs);
|
|
189
|
+
`,
|
|
190
|
+
errors: [{ messageId: 'preferCanonicalArraySlicing' }],
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
name: 'Arr.skip(xs, 1) → Arr.tail(xs)',
|
|
194
|
+
code: dedent`
|
|
195
|
+
import { Arr } from 'ts-data-forge';
|
|
196
|
+
declare const xs: readonly number[];
|
|
197
|
+
const ys = Arr.skip(xs, 1);
|
|
198
|
+
`,
|
|
199
|
+
output: dedent`
|
|
200
|
+
import { Arr } from 'ts-data-forge';
|
|
201
|
+
declare const xs: readonly number[];
|
|
202
|
+
const ys = Arr.tail(xs);
|
|
203
|
+
`,
|
|
204
|
+
errors: [{ messageId: 'preferCanonicalArraySlicing' }],
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
name: 'aliased import: A.skip(xs, 1) → A.tail(xs)',
|
|
208
|
+
code: dedent`
|
|
209
|
+
import { Arr as A } from 'ts-data-forge';
|
|
210
|
+
declare const xs: readonly number[];
|
|
211
|
+
const ys = A.skip(xs, 1);
|
|
212
|
+
`,
|
|
213
|
+
output: dedent`
|
|
214
|
+
import { Arr as A } from 'ts-data-forge';
|
|
215
|
+
declare const xs: readonly number[];
|
|
216
|
+
const ys = A.tail(xs);
|
|
217
|
+
`,
|
|
218
|
+
errors: [{ messageId: 'preferCanonicalArraySlicing' }],
|
|
219
|
+
},
|
|
220
|
+
// ---- skip N ----
|
|
221
|
+
{
|
|
222
|
+
name: 'xs.toSpliced(0, 3) → Arr.skip(xs, 3)',
|
|
223
|
+
code: dedent`
|
|
224
|
+
declare const xs: readonly number[];
|
|
225
|
+
const ys = xs.toSpliced(0, 3);
|
|
226
|
+
`,
|
|
227
|
+
output: dedent`
|
|
228
|
+
import { Arr } from 'ts-data-forge';
|
|
229
|
+
declare const xs: readonly number[];
|
|
230
|
+
const ys = Arr.skip(xs, 3);
|
|
231
|
+
`,
|
|
232
|
+
errors: [{ messageId: 'preferCanonicalArraySlicing' }],
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
name: 'xs.slice(2) → Arr.skip(xs, 2)',
|
|
236
|
+
code: dedent`
|
|
237
|
+
declare const xs: readonly number[];
|
|
238
|
+
const ys = xs.slice(2);
|
|
239
|
+
`,
|
|
240
|
+
output: dedent`
|
|
241
|
+
import { Arr } from 'ts-data-forge';
|
|
242
|
+
declare const xs: readonly number[];
|
|
243
|
+
const ys = Arr.skip(xs, 2);
|
|
244
|
+
`,
|
|
245
|
+
errors: [{ messageId: 'preferCanonicalArraySlicing' }],
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
name: 'xs.filter((_, i) => i >= 2) → Arr.skip(xs, 2)',
|
|
249
|
+
code: dedent`
|
|
250
|
+
declare const xs: readonly number[];
|
|
251
|
+
const ys = xs.filter((_, i) => i >= 2);
|
|
252
|
+
`,
|
|
253
|
+
output: dedent`
|
|
254
|
+
import { Arr } from 'ts-data-forge';
|
|
255
|
+
declare const xs: readonly number[];
|
|
256
|
+
const ys = Arr.skip(xs, 2);
|
|
257
|
+
`,
|
|
258
|
+
errors: [{ messageId: 'preferCanonicalArraySlicing' }],
|
|
259
|
+
},
|
|
260
|
+
// ---- take N ----
|
|
261
|
+
{
|
|
262
|
+
name: 'xs.toSpliced(2) → Arr.take(xs, 2)',
|
|
263
|
+
code: dedent`
|
|
264
|
+
declare const xs: readonly number[];
|
|
265
|
+
const ys = xs.toSpliced(2);
|
|
266
|
+
`,
|
|
267
|
+
output: dedent`
|
|
268
|
+
import { Arr } from 'ts-data-forge';
|
|
269
|
+
declare const xs: readonly number[];
|
|
270
|
+
const ys = Arr.take(xs, 2);
|
|
271
|
+
`,
|
|
272
|
+
errors: [{ messageId: 'preferCanonicalArraySlicing' }],
|
|
273
|
+
},
|
|
274
|
+
{
|
|
275
|
+
name: 'xs.slice(0, 2) → Arr.take(xs, 2)',
|
|
276
|
+
code: dedent`
|
|
277
|
+
declare const xs: readonly number[];
|
|
278
|
+
const ys = xs.slice(0, 2);
|
|
279
|
+
`,
|
|
280
|
+
output: dedent`
|
|
281
|
+
import { Arr } from 'ts-data-forge';
|
|
282
|
+
declare const xs: readonly number[];
|
|
283
|
+
const ys = Arr.take(xs, 2);
|
|
284
|
+
`,
|
|
285
|
+
errors: [{ messageId: 'preferCanonicalArraySlicing' }],
|
|
286
|
+
},
|
|
287
|
+
{
|
|
288
|
+
name: 'xs.filter((_, i) => i < 2) → Arr.take(xs, 2)',
|
|
289
|
+
code: dedent`
|
|
290
|
+
declare const xs: readonly number[];
|
|
291
|
+
const ys = xs.filter((_, i) => i < 2);
|
|
292
|
+
`,
|
|
293
|
+
output: dedent`
|
|
294
|
+
import { Arr } from 'ts-data-forge';
|
|
295
|
+
declare const xs: readonly number[];
|
|
296
|
+
const ys = Arr.take(xs, 2);
|
|
297
|
+
`,
|
|
298
|
+
errors: [{ messageId: 'preferCanonicalArraySlicing' }],
|
|
299
|
+
},
|
|
300
|
+
// ---- butLast ----
|
|
301
|
+
{
|
|
302
|
+
name: 'xs.toSpliced(-1) → Arr.butLast(xs)',
|
|
303
|
+
code: dedent`
|
|
304
|
+
declare const xs: readonly number[];
|
|
305
|
+
const ys = xs.toSpliced(-1);
|
|
306
|
+
`,
|
|
307
|
+
output: dedent`
|
|
308
|
+
import { Arr } from 'ts-data-forge';
|
|
309
|
+
declare const xs: readonly number[];
|
|
310
|
+
const ys = Arr.butLast(xs);
|
|
311
|
+
`,
|
|
312
|
+
errors: [{ messageId: 'preferCanonicalArraySlicing' }],
|
|
313
|
+
},
|
|
314
|
+
{
|
|
315
|
+
name: 'xs.slice(0, -1) → Arr.butLast(xs)',
|
|
316
|
+
code: dedent`
|
|
317
|
+
declare const xs: readonly number[];
|
|
318
|
+
const ys = xs.slice(0, -1);
|
|
319
|
+
`,
|
|
320
|
+
output: dedent`
|
|
321
|
+
import { Arr } from 'ts-data-forge';
|
|
322
|
+
declare const xs: readonly number[];
|
|
323
|
+
const ys = Arr.butLast(xs);
|
|
324
|
+
`,
|
|
325
|
+
errors: [{ messageId: 'preferCanonicalArraySlicing' }],
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
name: 'xs.filter((_, i) => i < xs.length - 1) → Arr.butLast(xs)',
|
|
329
|
+
code: dedent`
|
|
330
|
+
declare const xs: readonly number[];
|
|
331
|
+
const ys = xs.filter((_, i) => i < xs.length - 1);
|
|
332
|
+
`,
|
|
333
|
+
output: dedent`
|
|
334
|
+
import { Arr } from 'ts-data-forge';
|
|
335
|
+
declare const xs: readonly number[];
|
|
336
|
+
const ys = Arr.butLast(xs);
|
|
337
|
+
`,
|
|
338
|
+
errors: [{ messageId: 'preferCanonicalArraySlicing' }],
|
|
339
|
+
},
|
|
340
|
+
{
|
|
341
|
+
name: 'xs.filter((_, i) => i !== xs.length - 1) → Arr.butLast(xs)',
|
|
342
|
+
code: dedent`
|
|
343
|
+
declare const xs: readonly number[];
|
|
344
|
+
const ys = xs.filter((_, i) => i !== xs.length - 1);
|
|
345
|
+
`,
|
|
346
|
+
output: dedent`
|
|
347
|
+
import { Arr } from 'ts-data-forge';
|
|
348
|
+
declare const xs: readonly number[];
|
|
349
|
+
const ys = Arr.butLast(xs);
|
|
350
|
+
`,
|
|
351
|
+
errors: [{ messageId: 'preferCanonicalArraySlicing' }],
|
|
352
|
+
},
|
|
353
|
+
{
|
|
354
|
+
name: 'Arr.skipLast(xs, 1) → Arr.butLast(xs)',
|
|
355
|
+
code: dedent`
|
|
356
|
+
import { Arr } from 'ts-data-forge';
|
|
357
|
+
declare const xs: readonly number[];
|
|
358
|
+
const ys = Arr.skipLast(xs, 1);
|
|
359
|
+
`,
|
|
360
|
+
output: dedent`
|
|
361
|
+
import { Arr } from 'ts-data-forge';
|
|
362
|
+
declare const xs: readonly number[];
|
|
363
|
+
const ys = Arr.butLast(xs);
|
|
364
|
+
`,
|
|
365
|
+
errors: [{ messageId: 'preferCanonicalArraySlicing' }],
|
|
366
|
+
},
|
|
367
|
+
// ---- skipLast N ----
|
|
368
|
+
{
|
|
369
|
+
name: 'xs.toSpliced(-2) → Arr.skipLast(xs, 2)',
|
|
370
|
+
code: dedent`
|
|
371
|
+
declare const xs: readonly number[];
|
|
372
|
+
const ys = xs.toSpliced(-2);
|
|
373
|
+
`,
|
|
374
|
+
output: dedent`
|
|
375
|
+
import { Arr } from 'ts-data-forge';
|
|
376
|
+
declare const xs: readonly number[];
|
|
377
|
+
const ys = Arr.skipLast(xs, 2);
|
|
378
|
+
`,
|
|
379
|
+
errors: [{ messageId: 'preferCanonicalArraySlicing' }],
|
|
380
|
+
},
|
|
381
|
+
{
|
|
382
|
+
name: 'xs.slice(0, -2) → Arr.skipLast(xs, 2)',
|
|
383
|
+
code: dedent`
|
|
384
|
+
declare const xs: readonly number[];
|
|
385
|
+
const ys = xs.slice(0, -2);
|
|
386
|
+
`,
|
|
387
|
+
output: dedent`
|
|
388
|
+
import { Arr } from 'ts-data-forge';
|
|
389
|
+
declare const xs: readonly number[];
|
|
390
|
+
const ys = Arr.skipLast(xs, 2);
|
|
391
|
+
`,
|
|
392
|
+
errors: [{ messageId: 'preferCanonicalArraySlicing' }],
|
|
393
|
+
},
|
|
394
|
+
{
|
|
395
|
+
name: 'xs.filter((_, i) => i < xs.length - 2) → Arr.skipLast(xs, 2)',
|
|
396
|
+
code: dedent`
|
|
397
|
+
declare const xs: readonly number[];
|
|
398
|
+
const ys = xs.filter((_, i) => i < xs.length - 2);
|
|
399
|
+
`,
|
|
400
|
+
output: dedent`
|
|
401
|
+
import { Arr } from 'ts-data-forge';
|
|
402
|
+
declare const xs: readonly number[];
|
|
403
|
+
const ys = Arr.skipLast(xs, 2);
|
|
404
|
+
`,
|
|
405
|
+
errors: [{ messageId: 'preferCanonicalArraySlicing' }],
|
|
406
|
+
},
|
|
407
|
+
// ---- takeLast N ----
|
|
408
|
+
{
|
|
409
|
+
name: 'xs.slice(-2) → Arr.takeLast(xs, 2)',
|
|
410
|
+
code: dedent`
|
|
411
|
+
declare const xs: readonly number[];
|
|
412
|
+
const ys = xs.slice(-2);
|
|
413
|
+
`,
|
|
414
|
+
output: dedent`
|
|
415
|
+
import { Arr } from 'ts-data-forge';
|
|
416
|
+
declare const xs: readonly number[];
|
|
417
|
+
const ys = Arr.takeLast(xs, 2);
|
|
418
|
+
`,
|
|
419
|
+
errors: [{ messageId: 'preferCanonicalArraySlicing' }],
|
|
420
|
+
},
|
|
421
|
+
{
|
|
422
|
+
name: 'xs.filter((_, i) => i >= xs.length - 2) → Arr.takeLast(xs, 2)',
|
|
423
|
+
code: dedent`
|
|
424
|
+
declare const xs: readonly number[];
|
|
425
|
+
const ys = xs.filter((_, i) => i >= xs.length - 2);
|
|
426
|
+
`,
|
|
427
|
+
output: dedent`
|
|
428
|
+
import { Arr } from 'ts-data-forge';
|
|
429
|
+
declare const xs: readonly number[];
|
|
430
|
+
const ys = Arr.takeLast(xs, 2);
|
|
431
|
+
`,
|
|
432
|
+
errors: [{ messageId: 'preferCanonicalArraySlicing' }],
|
|
433
|
+
},
|
|
434
|
+
{
|
|
435
|
+
name: 'xs.toSpliced(0, xs.length - 2) → Arr.takeLast(xs, 2)',
|
|
436
|
+
code: dedent`
|
|
437
|
+
declare const xs: readonly number[];
|
|
438
|
+
const ys = xs.toSpliced(0, xs.length - 2);
|
|
439
|
+
`,
|
|
440
|
+
output: dedent`
|
|
441
|
+
import { Arr } from 'ts-data-forge';
|
|
442
|
+
declare const xs: readonly number[];
|
|
443
|
+
const ys = Arr.takeLast(xs, 2);
|
|
444
|
+
`,
|
|
445
|
+
errors: [{ messageId: 'preferCanonicalArraySlicing' }],
|
|
446
|
+
},
|
|
447
|
+
// ---- toUnshifted ----
|
|
448
|
+
{
|
|
449
|
+
name: '[v, ...xs] → Arr.toUnshifted(v)(xs)',
|
|
450
|
+
code: dedent`
|
|
451
|
+
declare const xs: readonly number[];
|
|
452
|
+
declare const v: number;
|
|
453
|
+
const ys = [v, ...xs];
|
|
454
|
+
`,
|
|
455
|
+
output: dedent`
|
|
456
|
+
import { Arr } from 'ts-data-forge';
|
|
457
|
+
declare const xs: readonly number[];
|
|
458
|
+
declare const v: number;
|
|
459
|
+
const ys = Arr.toUnshifted(v)(xs);
|
|
460
|
+
`,
|
|
461
|
+
errors: [{ messageId: 'preferCanonicalArraySlicing' }],
|
|
462
|
+
},
|
|
463
|
+
{
|
|
464
|
+
name: '[v].concat(xs) → Arr.toUnshifted(v)(xs)',
|
|
465
|
+
code: dedent`
|
|
466
|
+
declare const xs: readonly number[];
|
|
467
|
+
declare const v: number;
|
|
468
|
+
const ys = [v].concat(xs);
|
|
469
|
+
`,
|
|
470
|
+
output: dedent`
|
|
471
|
+
import { Arr } from 'ts-data-forge';
|
|
472
|
+
declare const xs: readonly number[];
|
|
473
|
+
declare const v: number;
|
|
474
|
+
const ys = Arr.toUnshifted(v)(xs);
|
|
475
|
+
`,
|
|
476
|
+
errors: [{ messageId: 'preferCanonicalArraySlicing' }],
|
|
477
|
+
},
|
|
478
|
+
{
|
|
479
|
+
name: 'xs.toSpliced(0, 0, v) → Arr.toUnshifted(v)(xs)',
|
|
480
|
+
code: dedent`
|
|
481
|
+
declare const xs: readonly number[];
|
|
482
|
+
declare const v: number;
|
|
483
|
+
const ys = xs.toSpliced(0, 0, v);
|
|
484
|
+
`,
|
|
485
|
+
output: dedent`
|
|
486
|
+
import { Arr } from 'ts-data-forge';
|
|
487
|
+
declare const xs: readonly number[];
|
|
488
|
+
declare const v: number;
|
|
489
|
+
const ys = Arr.toUnshifted(v)(xs);
|
|
490
|
+
`,
|
|
491
|
+
errors: [{ messageId: 'preferCanonicalArraySlicing' }],
|
|
492
|
+
},
|
|
493
|
+
// ---- toPushed ----
|
|
494
|
+
{
|
|
495
|
+
name: '[...xs, v] → Arr.toPushed(xs, v)',
|
|
496
|
+
code: dedent`
|
|
497
|
+
declare const xs: readonly number[];
|
|
498
|
+
declare const v: number;
|
|
499
|
+
const ys = [...xs, v];
|
|
500
|
+
`,
|
|
501
|
+
output: dedent`
|
|
502
|
+
import { Arr } from 'ts-data-forge';
|
|
503
|
+
declare const xs: readonly number[];
|
|
504
|
+
declare const v: number;
|
|
505
|
+
const ys = Arr.toPushed(xs, v);
|
|
506
|
+
`,
|
|
507
|
+
errors: [{ messageId: 'preferCanonicalArraySlicing' }],
|
|
508
|
+
},
|
|
509
|
+
{
|
|
510
|
+
name: 'xs.concat(v) with a non-array value → Arr.toPushed(xs, v)',
|
|
511
|
+
code: dedent`
|
|
512
|
+
declare const xs: readonly number[];
|
|
513
|
+
declare const v: number;
|
|
514
|
+
const ys = xs.concat(v);
|
|
515
|
+
`,
|
|
516
|
+
output: dedent`
|
|
517
|
+
import { Arr } from 'ts-data-forge';
|
|
518
|
+
declare const xs: readonly number[];
|
|
519
|
+
declare const v: number;
|
|
520
|
+
const ys = Arr.toPushed(xs, v);
|
|
521
|
+
`,
|
|
522
|
+
errors: [{ messageId: 'preferCanonicalArraySlicing' }],
|
|
523
|
+
},
|
|
524
|
+
{
|
|
525
|
+
name: 'xs.concat([v]) → Arr.toPushed(xs, v)',
|
|
526
|
+
code: dedent`
|
|
527
|
+
declare const xs: readonly number[];
|
|
528
|
+
declare const v: number;
|
|
529
|
+
const ys = xs.concat([v]);
|
|
530
|
+
`,
|
|
531
|
+
output: dedent`
|
|
532
|
+
import { Arr } from 'ts-data-forge';
|
|
533
|
+
declare const xs: readonly number[];
|
|
534
|
+
declare const v: number;
|
|
535
|
+
const ys = Arr.toPushed(xs, v);
|
|
536
|
+
`,
|
|
537
|
+
errors: [{ messageId: 'preferCanonicalArraySlicing' }],
|
|
538
|
+
},
|
|
539
|
+
{
|
|
540
|
+
name: 'xs.toSpliced(xs.length, 0, v) → Arr.toPushed(xs, v)',
|
|
541
|
+
code: dedent`
|
|
542
|
+
declare const xs: readonly number[];
|
|
543
|
+
declare const v: number;
|
|
544
|
+
const ys = xs.toSpliced(xs.length, 0, v);
|
|
545
|
+
`,
|
|
546
|
+
output: dedent`
|
|
547
|
+
import { Arr } from 'ts-data-forge';
|
|
548
|
+
declare const xs: readonly number[];
|
|
549
|
+
declare const v: number;
|
|
550
|
+
const ys = Arr.toPushed(xs, v);
|
|
551
|
+
`,
|
|
552
|
+
errors: [{ messageId: 'preferCanonicalArraySlicing' }],
|
|
553
|
+
},
|
|
554
|
+
// ---- misc ----
|
|
555
|
+
{
|
|
556
|
+
name: 'member-expression receiver is supported',
|
|
557
|
+
code: dedent`
|
|
558
|
+
declare const obj: { items: readonly number[] };
|
|
559
|
+
const ys = obj.items.filter((_, i) => i < obj.items.length - 1);
|
|
560
|
+
`,
|
|
561
|
+
output: dedent`
|
|
562
|
+
import { Arr } from 'ts-data-forge';
|
|
563
|
+
declare const obj: { items: readonly number[] };
|
|
564
|
+
const ys = Arr.butLast(obj.items);
|
|
565
|
+
`,
|
|
566
|
+
errors: [{ messageId: 'preferCanonicalArraySlicing' }],
|
|
567
|
+
},
|
|
568
|
+
{
|
|
569
|
+
name: 'the import is inserted only once for multiple fixes',
|
|
570
|
+
code: dedent`
|
|
571
|
+
declare const xs: readonly number[];
|
|
572
|
+
const ys = xs.slice(1);
|
|
573
|
+
const zs = xs.slice(0, -1);
|
|
574
|
+
`,
|
|
575
|
+
output: dedent`
|
|
576
|
+
import { Arr } from 'ts-data-forge';
|
|
577
|
+
declare const xs: readonly number[];
|
|
578
|
+
const ys = Arr.tail(xs);
|
|
579
|
+
const zs = Arr.butLast(xs);
|
|
580
|
+
`,
|
|
581
|
+
errors: [
|
|
582
|
+
{ messageId: 'preferCanonicalArraySlicing' },
|
|
583
|
+
{ messageId: 'preferCanonicalArraySlicing' },
|
|
584
|
+
],
|
|
585
|
+
},
|
|
586
|
+
],
|
|
587
|
+
});
|
|
588
|
+
});
|