eslint-plugin-ts-data-forge 0.10.5 → 0.10.6
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/dist/rules/ast-utils.d.mts +5 -5
- package/dist/rules/ast-utils.d.mts.map +1 -1
- package/dist/rules/ast-utils.mjs +3 -3
- package/dist/rules/ast-utils.mjs.map +1 -1
- package/dist/rules/import-binding.d.mts +38 -0
- package/dist/rules/import-binding.d.mts.map +1 -0
- package/dist/rules/import-binding.mjs +53 -0
- package/dist/rules/import-binding.mjs.map +1 -0
- package/dist/rules/mutable-result.mjs +37 -37
- package/dist/rules/mutable-result.mjs.map +1 -1
- package/dist/rules/no-unnecessary-type-guard.d.mts.map +1 -1
- package/dist/rules/no-unnecessary-type-guard.mjs +146 -143
- package/dist/rules/no-unnecessary-type-guard.mjs.map +1 -1
- package/dist/rules/prefer-arr-generate.d.mts.map +1 -1
- package/dist/rules/prefer-arr-generate.mjs +129 -131
- package/dist/rules/prefer-arr-generate.mjs.map +1 -1
- package/dist/rules/prefer-arr-is-bounded-length-array.d.mts.map +1 -1
- package/dist/rules/prefer-arr-is-bounded-length-array.mjs +14 -16
- package/dist/rules/prefer-arr-is-bounded-length-array.mjs.map +1 -1
- package/dist/rules/prefer-arr-is-fixed-length-array.d.mts.map +1 -1
- package/dist/rules/prefer-arr-is-fixed-length-array.mjs +15 -17
- package/dist/rules/prefer-arr-is-fixed-length-array.mjs.map +1 -1
- package/dist/rules/prefer-arr-is-max-length-array.d.mts.map +1 -1
- package/dist/rules/prefer-arr-is-max-length-array.mjs +14 -16
- package/dist/rules/prefer-arr-is-max-length-array.mjs.map +1 -1
- package/dist/rules/prefer-arr-is-min-length-array.d.mts.map +1 -1
- package/dist/rules/prefer-arr-is-min-length-array.mjs +14 -16
- package/dist/rules/prefer-arr-is-min-length-array.mjs.map +1 -1
- package/dist/rules/prefer-arr-is-non-empty.d.mts.map +1 -1
- package/dist/rules/prefer-arr-is-non-empty.mjs +14 -16
- package/dist/rules/prefer-arr-is-non-empty.mjs.map +1 -1
- package/dist/rules/prefer-arr-scan.d.mts.map +1 -1
- package/dist/rules/prefer-arr-scan.mjs +9 -18
- package/dist/rules/prefer-arr-scan.mjs.map +1 -1
- package/dist/rules/prefer-arr-sum.d.mts.map +1 -1
- package/dist/rules/prefer-arr-sum.mjs +16 -21
- package/dist/rules/prefer-arr-sum.mjs.map +1 -1
- package/dist/rules/prefer-arr-uniq.d.mts.map +1 -1
- package/dist/rules/prefer-arr-uniq.mjs +38 -43
- package/dist/rules/prefer-arr-uniq.mjs.map +1 -1
- package/dist/rules/prefer-as-int.d.mts.map +1 -1
- package/dist/rules/prefer-as-int.mjs +19 -26
- package/dist/rules/prefer-as-int.mjs.map +1 -1
- package/dist/rules/prefer-canonical-array-slicing.d.mts.map +1 -1
- package/dist/rules/prefer-canonical-array-slicing.mjs +49 -15
- package/dist/rules/prefer-canonical-array-slicing.mjs.map +1 -1
- package/dist/rules/prefer-canonical-length-cast.mjs +15 -15
- package/dist/rules/prefer-canonical-length-cast.mjs.map +1 -1
- package/dist/rules/prefer-obj-over-entries-round-trip.d.mts.map +1 -1
- package/dist/rules/prefer-obj-over-entries-round-trip.mjs +100 -99
- package/dist/rules/prefer-obj-over-entries-round-trip.mjs.map +1 -1
- package/dist/rules/prefer-pipe-map-nullable.d.mts.map +1 -1
- package/dist/rules/prefer-pipe-map-nullable.mjs +2 -4
- package/dist/rules/prefer-pipe-map-nullable.mjs.map +1 -1
- package/dist/rules/prefer-range-for-loop.d.mts.map +1 -1
- package/dist/rules/prefer-range-for-loop.mjs +18 -24
- package/dist/rules/prefer-range-for-loop.mjs.map +1 -1
- package/package.json +4 -4
- package/src/rules/ast-utils.mts +11 -11
- package/src/rules/import-binding.mts +94 -0
- package/src/rules/mutable-result.mts +56 -56
- package/src/rules/no-unnecessary-type-guard.mts +199 -203
- package/src/rules/no-unnecessary-type-guard.test.mts +62 -2
- package/src/rules/prefer-arr-generate.mts +184 -194
- package/src/rules/prefer-arr-generate.test.mts +262 -134
- package/src/rules/prefer-arr-is-bounded-length-array.mts +22 -33
- package/src/rules/prefer-arr-is-fixed-length-array.mts +24 -36
- package/src/rules/prefer-arr-is-fixed-length-array.test.mts +16 -7
- package/src/rules/prefer-arr-is-max-length-array.mts +21 -34
- package/src/rules/prefer-arr-is-max-length-array.test.mts +16 -7
- package/src/rules/prefer-arr-is-min-length-array.mts +21 -34
- package/src/rules/prefer-arr-is-min-length-array.test.mts +16 -7
- package/src/rules/prefer-arr-is-non-empty.mts +17 -34
- package/src/rules/prefer-arr-is-non-empty.test.mts +110 -0
- package/src/rules/prefer-arr-scan.mts +11 -36
- package/src/rules/prefer-arr-scan.test.mts +55 -0
- package/src/rules/prefer-arr-sum.mts +19 -33
- package/src/rules/prefer-arr-uniq.mts +49 -60
- package/src/rules/prefer-arr-uniq.test.mts +46 -20
- package/src/rules/prefer-as-int.mts +27 -52
- package/src/rules/prefer-as-int.test.mts +79 -29
- package/src/rules/prefer-canonical-array-slicing.mts +86 -24
- package/src/rules/prefer-canonical-array-slicing.test.mts +133 -34
- package/src/rules/prefer-canonical-length-cast.mts +18 -18
- package/src/rules/prefer-obj-over-entries-round-trip.mts +152 -170
- package/src/rules/prefer-obj-over-entries-round-trip.test.mts +48 -6
- package/src/rules/prefer-pipe-map-nullable.mts +6 -8
- package/src/rules/prefer-range-for-loop.mts +31 -55
|
@@ -5,11 +5,14 @@ import {
|
|
|
5
5
|
type TSESTree,
|
|
6
6
|
} from '@typescript-eslint/utils';
|
|
7
7
|
import {
|
|
8
|
-
|
|
8
|
+
bindValueImports,
|
|
9
9
|
getImportDeclarations,
|
|
10
10
|
getImportedLocalName,
|
|
11
|
+
hasForeignBinding,
|
|
12
|
+
importedNameOf,
|
|
11
13
|
skipTypeWrappers,
|
|
12
14
|
typeWrapperLayers,
|
|
15
|
+
type ValueImportBinding,
|
|
13
16
|
} from 'eslint-rule-forge';
|
|
14
17
|
import type { ReadonlyRecord } from 'ts-type-forge';
|
|
15
18
|
import * as ts from 'typescript';
|
|
@@ -210,10 +213,16 @@ export const preferCanonicalArraySlicing: TSESLint.RuleModule<
|
|
|
210
213
|
const checker = parserServices.program.getTypeChecker();
|
|
211
214
|
|
|
212
215
|
/**
|
|
213
|
-
* The in-scope way to reference the `Arr` namespace
|
|
214
|
-
*
|
|
215
|
-
*
|
|
216
|
+
* The in-scope way to reference the `Arr` namespace, the name the
|
|
217
|
+
* reference starts with, and the edits that bring it into scope: a value
|
|
218
|
+
* import of `Arr` (possibly aliased), a namespace import member, or `Arr`
|
|
219
|
+
* bound by {@link bindValueImports}, which adds it to an existing import or
|
|
220
|
+
* drops `type` from one. `undefined` when none can: `import type { Arr }`
|
|
221
|
+
* with no namespace import.
|
|
216
222
|
*/
|
|
223
|
+
const arrTarget = resolveArrTarget(sourceCode, tsDataForgeImports);
|
|
224
|
+
|
|
225
|
+
/** How a call already in the file names `Arr`, to recognize it. */
|
|
217
226
|
const arrLocalName = getImportedLocalName(tsDataForgeImports, 'Arr');
|
|
218
227
|
|
|
219
228
|
const namespaceLocalName = tsDataForgeImports
|
|
@@ -223,12 +232,7 @@ export const preferCanonicalArraySlicing: TSESLint.RuleModule<
|
|
|
223
232
|
specifier.type === AST_NODE_TYPES.ImportNamespaceSpecifier,
|
|
224
233
|
)?.local.name;
|
|
225
234
|
|
|
226
|
-
const arrRef =
|
|
227
|
-
arrLocalName ??
|
|
228
|
-
(namespaceLocalName === undefined ? 'Arr' : `${namespaceLocalName}.Arr`);
|
|
229
|
-
|
|
230
|
-
const needsArrImport =
|
|
231
|
-
arrLocalName === undefined && namespaceLocalName === undefined;
|
|
235
|
+
const arrRef = arrTarget?.ref ?? 'Arr';
|
|
232
236
|
|
|
233
237
|
/**
|
|
234
238
|
* Deferred (non-concrete) types are reduced to their base constraint
|
|
@@ -855,27 +859,85 @@ export const preferCanonicalArraySlicing: TSESLint.RuleModule<
|
|
|
855
859
|
},
|
|
856
860
|
|
|
857
861
|
'Program:exit': () => {
|
|
858
|
-
|
|
862
|
+
// Every fix brings `Arr` into scope itself, so that one applied alone
|
|
863
|
+
// (an editor's quick fix) is complete.
|
|
864
|
+
for (const nodeInfo of mut_nodesToFix) {
|
|
865
|
+
const writable =
|
|
866
|
+
arrTarget !== undefined &&
|
|
867
|
+
!hasForeignBinding(
|
|
868
|
+
sourceCode,
|
|
869
|
+
nodeInfo.node,
|
|
870
|
+
arrTarget.boundName,
|
|
871
|
+
TS_DATA_FORGE_MODULE,
|
|
872
|
+
);
|
|
873
|
+
|
|
859
874
|
context.report({
|
|
860
875
|
node: nodeInfo.node,
|
|
861
876
|
messageId: 'preferCanonicalArraySlicing',
|
|
862
877
|
data: { replacement: nodeInfo.replacement },
|
|
863
|
-
fix:
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
: [];
|
|
870
|
-
|
|
871
|
-
return [
|
|
872
|
-
...importFixes,
|
|
873
|
-
fixer.replaceText(nodeInfo.node, nodeInfo.replacement),
|
|
874
|
-
];
|
|
875
|
-
},
|
|
878
|
+
fix: writable
|
|
879
|
+
? (fixer) => [
|
|
880
|
+
...arrTarget.edits(fixer),
|
|
881
|
+
fixer.replaceText(nodeInfo.node, nodeInfo.replacement),
|
|
882
|
+
]
|
|
883
|
+
: null,
|
|
876
884
|
});
|
|
877
885
|
}
|
|
878
886
|
},
|
|
879
887
|
};
|
|
880
888
|
},
|
|
881
889
|
} as const;
|
|
890
|
+
|
|
891
|
+
/**
|
|
892
|
+
* How `Arr` is written in this file; see where it is called. A value import of
|
|
893
|
+
* `Arr` comes first, then a namespace import, and only then an edit.
|
|
894
|
+
*/
|
|
895
|
+
const resolveArrTarget = (
|
|
896
|
+
sourceCode: TSESLint.SourceCode,
|
|
897
|
+
tsDataForgeImports: readonly TSESTree.ImportDeclaration[],
|
|
898
|
+
):
|
|
899
|
+
| Readonly<{
|
|
900
|
+
ref: string;
|
|
901
|
+
boundName: string;
|
|
902
|
+
edits: ValueImportBinding['edits'];
|
|
903
|
+
}>
|
|
904
|
+
| undefined => {
|
|
905
|
+
const valueSpecifiers = tsDataForgeImports
|
|
906
|
+
.filter((declaration) => declaration.importKind !== 'type')
|
|
907
|
+
.flatMap((declaration) => declaration.specifiers);
|
|
908
|
+
|
|
909
|
+
const arrImport = valueSpecifiers.find(
|
|
910
|
+
(specifier) =>
|
|
911
|
+
specifier.type === AST_NODE_TYPES.ImportSpecifier &&
|
|
912
|
+
specifier.importKind !== 'type' &&
|
|
913
|
+
importedNameOf(specifier) === 'Arr',
|
|
914
|
+
);
|
|
915
|
+
|
|
916
|
+
if (arrImport !== undefined) {
|
|
917
|
+
return {
|
|
918
|
+
ref: arrImport.local.name,
|
|
919
|
+
boundName: arrImport.local.name,
|
|
920
|
+
edits: () => [],
|
|
921
|
+
};
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
const namespace = valueSpecifiers.find(
|
|
925
|
+
(specifier) => specifier.type === AST_NODE_TYPES.ImportNamespaceSpecifier,
|
|
926
|
+
);
|
|
927
|
+
|
|
928
|
+
if (namespace !== undefined) {
|
|
929
|
+
return {
|
|
930
|
+
ref: `${namespace.local.name}.Arr`,
|
|
931
|
+
boundName: namespace.local.name,
|
|
932
|
+
edits: () => [],
|
|
933
|
+
};
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
const binding = bindValueImports(sourceCode, TS_DATA_FORGE_MODULE, ['Arr']);
|
|
937
|
+
|
|
938
|
+
const localName = binding?.localNames[0];
|
|
939
|
+
|
|
940
|
+
return binding === undefined || localName === undefined
|
|
941
|
+
? undefined
|
|
942
|
+
: { ref: localName, boundName: localName, edits: binding.edits };
|
|
943
|
+
};
|
|
@@ -572,12 +572,20 @@ describe('prefer-canonical-array-slicing', () => {
|
|
|
572
572
|
const ys = xs.slice(1);
|
|
573
573
|
const zs = xs.slice(0, -1);
|
|
574
574
|
`,
|
|
575
|
-
output:
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
575
|
+
output: [
|
|
576
|
+
dedent`
|
|
577
|
+
import { Arr } from 'ts-data-forge';
|
|
578
|
+
declare const xs: readonly number[];
|
|
579
|
+
const ys = Arr.tail(xs);
|
|
580
|
+
const zs = xs.slice(0, -1);
|
|
581
|
+
`,
|
|
582
|
+
dedent`
|
|
583
|
+
import { Arr } from 'ts-data-forge';
|
|
584
|
+
declare const xs: readonly number[];
|
|
585
|
+
const ys = Arr.tail(xs);
|
|
586
|
+
const zs = Arr.butLast(xs);
|
|
587
|
+
`,
|
|
588
|
+
],
|
|
581
589
|
errors: [
|
|
582
590
|
{ messageId: 'preferCanonicalArraySlicing' },
|
|
583
591
|
{ messageId: 'preferCanonicalArraySlicing' },
|
|
@@ -629,13 +637,22 @@ describe('prefer-canonical-array-slicing through type wrappers', () => {
|
|
|
629
637
|
const b = xs.slice(0 satisfies number, -1 as number);
|
|
630
638
|
const c = xs.toSpliced(2 satisfies number);
|
|
631
639
|
`,
|
|
632
|
-
output:
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
640
|
+
output: [
|
|
641
|
+
dedent`
|
|
642
|
+
import { Arr } from 'ts-data-forge';
|
|
643
|
+
declare const xs: readonly number[];
|
|
644
|
+
const a = Arr.tail(xs);
|
|
645
|
+
const b = xs.slice(0 satisfies number, -1 as number);
|
|
646
|
+
const c = xs.toSpliced(2 satisfies number);
|
|
647
|
+
`,
|
|
648
|
+
dedent`
|
|
649
|
+
import { Arr } from 'ts-data-forge';
|
|
650
|
+
declare const xs: readonly number[];
|
|
651
|
+
const a = Arr.tail(xs);
|
|
652
|
+
const b = Arr.butLast(xs);
|
|
653
|
+
const c = Arr.take(xs, 2);
|
|
654
|
+
`,
|
|
655
|
+
],
|
|
639
656
|
errors: [
|
|
640
657
|
{ messageId: 'preferCanonicalArraySlicing' },
|
|
641
658
|
{ messageId: 'preferCanonicalArraySlicing' },
|
|
@@ -663,13 +680,22 @@ describe('prefer-canonical-array-slicing through type wrappers', () => {
|
|
|
663
680
|
const ys = (xs satisfies readonly number[]).slice(1);
|
|
664
681
|
const zs = [...xs!, v!];
|
|
665
682
|
`,
|
|
666
|
-
output:
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
683
|
+
output: [
|
|
684
|
+
dedent`
|
|
685
|
+
import { Arr } from 'ts-data-forge';
|
|
686
|
+
declare const xs: readonly number[];
|
|
687
|
+
declare const v: number | undefined;
|
|
688
|
+
const ys = Arr.tail(xs satisfies readonly number[]);
|
|
689
|
+
const zs = [...xs!, v!];
|
|
690
|
+
`,
|
|
691
|
+
dedent`
|
|
692
|
+
import { Arr } from 'ts-data-forge';
|
|
693
|
+
declare const xs: readonly number[];
|
|
694
|
+
declare const v: number | undefined;
|
|
695
|
+
const ys = Arr.tail(xs satisfies readonly number[]);
|
|
696
|
+
const zs = Arr.toPushed(xs!, v!);
|
|
697
|
+
`,
|
|
698
|
+
],
|
|
673
699
|
errors: [
|
|
674
700
|
{ messageId: 'preferCanonicalArraySlicing' },
|
|
675
701
|
{ messageId: 'preferCanonicalArraySlicing' },
|
|
@@ -697,14 +723,24 @@ describe('prefer-canonical-array-slicing through type wrappers', () => {
|
|
|
697
723
|
const c = xs.filter((_, i) => i < (xs.length satisfies number) - 2);
|
|
698
724
|
const d = xs.toSpliced(0, xs!.length - 2);
|
|
699
725
|
`,
|
|
700
|
-
output:
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
726
|
+
output: [
|
|
727
|
+
dedent`
|
|
728
|
+
import { Arr } from 'ts-data-forge';
|
|
729
|
+
declare const xs: readonly number[];
|
|
730
|
+
const a = Arr.butLast(xs);
|
|
731
|
+
const b = xs.slice(0, (xs as readonly number[]).length - 1);
|
|
732
|
+
const c = xs.filter((_, i) => i < (xs.length satisfies number) - 2);
|
|
733
|
+
const d = xs.toSpliced(0, xs!.length - 2);
|
|
734
|
+
`,
|
|
735
|
+
dedent`
|
|
736
|
+
import { Arr } from 'ts-data-forge';
|
|
737
|
+
declare const xs: readonly number[];
|
|
738
|
+
const a = Arr.butLast(xs);
|
|
739
|
+
const b = Arr.butLast(xs);
|
|
740
|
+
const c = Arr.skipLast(xs, 2);
|
|
741
|
+
const d = Arr.takeLast(xs, 2);
|
|
742
|
+
`,
|
|
743
|
+
],
|
|
708
744
|
errors: [
|
|
709
745
|
{ messageId: 'preferCanonicalArraySlicing' },
|
|
710
746
|
{ messageId: 'preferCanonicalArraySlicing' },
|
|
@@ -719,12 +755,20 @@ describe('prefer-canonical-array-slicing through type wrappers', () => {
|
|
|
719
755
|
const a = (xs satisfies readonly number[]).slice(0, xs.length - 1);
|
|
720
756
|
const b = xs.toSpliced((xs.length as number), 0, 1);
|
|
721
757
|
`,
|
|
722
|
-
output:
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
758
|
+
output: [
|
|
759
|
+
dedent`
|
|
760
|
+
import { Arr } from 'ts-data-forge';
|
|
761
|
+
declare const xs: readonly number[];
|
|
762
|
+
const a = Arr.butLast(xs satisfies readonly number[]);
|
|
763
|
+
const b = xs.toSpliced((xs.length as number), 0, 1);
|
|
764
|
+
`,
|
|
765
|
+
dedent`
|
|
766
|
+
import { Arr } from 'ts-data-forge';
|
|
767
|
+
declare const xs: readonly number[];
|
|
768
|
+
const a = Arr.butLast(xs satisfies readonly number[]);
|
|
769
|
+
const b = Arr.toPushed(xs, 1);
|
|
770
|
+
`,
|
|
771
|
+
],
|
|
728
772
|
errors: [
|
|
729
773
|
{ messageId: 'preferCanonicalArraySlicing' },
|
|
730
774
|
{ messageId: 'preferCanonicalArraySlicing' },
|
|
@@ -733,3 +777,58 @@ describe('prefer-canonical-array-slicing through type wrappers', () => {
|
|
|
733
777
|
],
|
|
734
778
|
});
|
|
735
779
|
});
|
|
780
|
+
|
|
781
|
+
describe('prefer-canonical-array-slicing and the import it adds', () => {
|
|
782
|
+
tester.run('prefer-canonical-array-slicing', preferCanonicalArraySlicing, {
|
|
783
|
+
valid: [],
|
|
784
|
+
invalid: [
|
|
785
|
+
{
|
|
786
|
+
name: 'writes through a namespace import, which needs no edit',
|
|
787
|
+
code: dedent`
|
|
788
|
+
import * as tdf from 'ts-data-forge';
|
|
789
|
+
declare const xs: readonly number[];
|
|
790
|
+
const ys = xs.slice(1);
|
|
791
|
+
`,
|
|
792
|
+
output: dedent`
|
|
793
|
+
import * as tdf from 'ts-data-forge';
|
|
794
|
+
declare const xs: readonly number[];
|
|
795
|
+
const ys = tdf.Arr.tail(xs);
|
|
796
|
+
`,
|
|
797
|
+
errors: [{ messageId: 'preferCanonicalArraySlicing' }],
|
|
798
|
+
},
|
|
799
|
+
{
|
|
800
|
+
name: 'joins an existing named import from the module',
|
|
801
|
+
code: dedent`
|
|
802
|
+
import { asInt } from 'ts-data-forge';
|
|
803
|
+
declare const xs: readonly number[];
|
|
804
|
+
const ys = xs.slice(1);
|
|
805
|
+
`,
|
|
806
|
+
output: dedent`
|
|
807
|
+
import { asInt, Arr } from 'ts-data-forge';
|
|
808
|
+
declare const xs: readonly number[];
|
|
809
|
+
const ys = Arr.tail(xs);
|
|
810
|
+
`,
|
|
811
|
+
errors: [{ messageId: 'preferCanonicalArraySlicing' }],
|
|
812
|
+
},
|
|
813
|
+
{
|
|
814
|
+
name: 'no fix when an import type binds the name',
|
|
815
|
+
code: dedent`
|
|
816
|
+
import type { Arr } from 'ts-data-forge';
|
|
817
|
+
declare const xs: readonly number[];
|
|
818
|
+
const ys = xs.slice(1);
|
|
819
|
+
`,
|
|
820
|
+
output: null,
|
|
821
|
+
errors: [{ messageId: 'preferCanonicalArraySlicing' }],
|
|
822
|
+
},
|
|
823
|
+
{
|
|
824
|
+
name: 'no fix where a local binding takes the name',
|
|
825
|
+
code: dedent`
|
|
826
|
+
declare const xs: readonly number[];
|
|
827
|
+
const f = (Arr: unknown) => xs.slice(1);
|
|
828
|
+
`,
|
|
829
|
+
output: null,
|
|
830
|
+
errors: [{ messageId: 'preferCanonicalArraySlicing' }],
|
|
831
|
+
},
|
|
832
|
+
],
|
|
833
|
+
});
|
|
834
|
+
});
|
|
@@ -218,6 +218,24 @@ const getCastName = (
|
|
|
218
218
|
: undefined;
|
|
219
219
|
};
|
|
220
220
|
|
|
221
|
+
/**
|
|
222
|
+
* A non-negative integer literal's value, or `undefined` for anything else.
|
|
223
|
+
* Read through type wrappers: `1 as const` is still the bound `1`.
|
|
224
|
+
*/
|
|
225
|
+
const getLengthLiteral = (
|
|
226
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
227
|
+
wrapped: TSESTree.Node,
|
|
228
|
+
): number | undefined => {
|
|
229
|
+
const node = skipTypeWrappers(wrapped);
|
|
230
|
+
|
|
231
|
+
return node.type === AST_NODE_TYPES.Literal &&
|
|
232
|
+
typeof node.value === 'number' &&
|
|
233
|
+
Number.isSafeInteger(node.value) &&
|
|
234
|
+
node.value >= 0
|
|
235
|
+
? node.value
|
|
236
|
+
: undefined;
|
|
237
|
+
};
|
|
238
|
+
|
|
221
239
|
/**
|
|
222
240
|
* Whether the call is `cast(...bounds, array)` with every bound written as the
|
|
223
241
|
* exact numeric literal the rewrite requires.
|
|
@@ -319,21 +337,3 @@ const dropBoundsFix = (
|
|
|
319
337
|
? []
|
|
320
338
|
: [fixer.removeRange([start.range[0], end.range[0]])];
|
|
321
339
|
});
|
|
322
|
-
|
|
323
|
-
/**
|
|
324
|
-
* A non-negative integer literal's value, or `undefined` for anything else.
|
|
325
|
-
* Read through type wrappers: `1 as const` is still the bound `1`.
|
|
326
|
-
*/
|
|
327
|
-
const getLengthLiteral = (
|
|
328
|
-
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
329
|
-
wrapped: TSESTree.Node,
|
|
330
|
-
): number | undefined => {
|
|
331
|
-
const node = skipTypeWrappers(wrapped);
|
|
332
|
-
|
|
333
|
-
return node.type === AST_NODE_TYPES.Literal &&
|
|
334
|
-
typeof node.value === 'number' &&
|
|
335
|
-
Number.isSafeInteger(node.value) &&
|
|
336
|
-
node.value >= 0
|
|
337
|
-
? node.value
|
|
338
|
-
: undefined;
|
|
339
|
-
};
|