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.
- package/README.md +3 -3
- package/dist/plugin.d.mts +2 -2
- package/dist/plugin.d.mts.map +1 -1
- package/dist/plugin.mjs +1 -0
- package/dist/plugin.mjs.map +1 -1
- package/dist/rule-types.d.mts +5 -5
- package/dist/rules/ast-utils.d.mts +8 -9
- package/dist/rules/ast-utils.d.mts.map +1 -1
- package/dist/rules/ast-utils.mjs +3 -4
- 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 +2 -2
- package/dist/rules/prefer-arr-generate.d.mts.map +1 -1
- package/dist/rules/prefer-arr-generate.mjs +146 -136
- 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 -16
- 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-num-safe-parse-float.d.mts +1 -1
- package/dist/rules/prefer-num-safe-parse-float.d.mts.map +1 -1
- package/dist/rules/prefer-num-safe-parse-int.d.mts +1 -1
- package/dist/rules/prefer-num-safe-parse-int.d.mts.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 +2 -2
- 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/dist/rules/rules.d.mts +2 -2
- package/package.json +6 -6
- package/src/plugin.mts +4 -3
- package/src/rule-types.mts +5 -5
- package/src/rules/ast-utils.mts +14 -15
- package/src/rules/import-binding.mts +94 -0
- package/src/rules/mutable-result.mts +56 -56
- package/src/rules/no-unnecessary-type-guard.mts +203 -207
- package/src/rules/no-unnecessary-type-guard.test.mts +62 -2
- package/src/rules/prefer-arr-generate.mts +222 -214
- package/src/rules/prefer-arr-generate.test.mts +490 -133
- package/src/rules/prefer-arr-is-bounded-length-array.mts +22 -33
- package/src/rules/prefer-arr-is-fixed-length-array.mts +26 -38
- package/src/rules/prefer-arr-is-fixed-length-array.test.mts +16 -7
- package/src/rules/prefer-arr-is-max-length-array.mts +23 -36
- package/src/rules/prefer-arr-is-max-length-array.test.mts +16 -7
- package/src/rules/prefer-arr-is-min-length-array.mts +23 -36
- 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 +17 -42
- package/src/rules/prefer-arr-scan.test.mts +55 -0
- package/src/rules/prefer-arr-sum.mts +22 -36
- package/src/rules/prefer-arr-uniq.mts +51 -62
- 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 +101 -40
- package/src/rules/prefer-canonical-array-slicing.test.mts +133 -34
- package/src/rules/prefer-canonical-length-cast.mts +29 -29
- package/src/rules/prefer-canonical-length-guard.mts +2 -2
- package/src/rules/prefer-num-safe-parse-float.test.mts +255 -94
- package/src/rules/prefer-num-safe-parse-int.test.mts +212 -76
- 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 +17 -19
- package/src/rules/prefer-range-for-loop.mts +37 -61
- package/src/rules/prefer-range-for-loop.test.mts +2 -2
|
@@ -1,16 +1,11 @@
|
|
|
1
1
|
import type { TSESLint, TSESTree } from '@typescript-eslint/utils';
|
|
2
|
-
import {
|
|
3
|
-
buildNamedImportFix,
|
|
4
|
-
getArgumentText,
|
|
5
|
-
getImportDeclarations,
|
|
6
|
-
getNamedImports,
|
|
7
|
-
} from 'eslint-rule-forge';
|
|
2
|
+
import { getArgumentText } from 'eslint-rule-forge';
|
|
8
3
|
import {
|
|
9
4
|
isArrayOrTupleExpression,
|
|
10
5
|
isSameArrayText,
|
|
11
6
|
parseLengthComparison,
|
|
12
7
|
} from './ast-utils.mjs';
|
|
13
|
-
import {
|
|
8
|
+
import { tsDataForgeValueAt } from './import-binding.mjs';
|
|
14
9
|
|
|
15
10
|
type Options = readonly [];
|
|
16
11
|
|
|
@@ -38,13 +33,6 @@ export const preferArrIsBoundedLengthArray: TSESLint.RuleModule<
|
|
|
38
33
|
create: (context) => {
|
|
39
34
|
const sourceCode = context.sourceCode;
|
|
40
35
|
|
|
41
|
-
const program = sourceCode.ast;
|
|
42
|
-
|
|
43
|
-
const tsDataForgeImports = getImportDeclarations(
|
|
44
|
-
program,
|
|
45
|
-
TS_DATA_FORGE_MODULE,
|
|
46
|
-
);
|
|
47
|
-
|
|
48
36
|
const services = context.sourceCode.parserServices;
|
|
49
37
|
|
|
50
38
|
const mut_nodesToFix: {
|
|
@@ -100,14 +88,14 @@ export const preferArrIsBoundedLengthArray: TSESLint.RuleModule<
|
|
|
100
88
|
});
|
|
101
89
|
},
|
|
102
90
|
'Program:exit': () => {
|
|
103
|
-
const
|
|
91
|
+
const arrAt = tsDataForgeValueAt(sourceCode, 'Arr');
|
|
104
92
|
|
|
105
|
-
const
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
93
|
+
for (const {
|
|
94
|
+
node,
|
|
95
|
+
arrayExpression,
|
|
96
|
+
minExpression,
|
|
97
|
+
maxExpression,
|
|
98
|
+
} of mut_nodesToFix) {
|
|
111
99
|
const arrayText = getArgumentText(sourceCode, arrayExpression);
|
|
112
100
|
|
|
113
101
|
const minText = sourceCode.getText(minExpression);
|
|
@@ -116,6 +104,8 @@ export const preferArrIsBoundedLengthArray: TSESLint.RuleModule<
|
|
|
116
104
|
|
|
117
105
|
const originalText = sourceCode.getText(node);
|
|
118
106
|
|
|
107
|
+
const arr = arrAt(node);
|
|
108
|
+
|
|
119
109
|
context.report({
|
|
120
110
|
node,
|
|
121
111
|
messageId: 'useIsBoundedLengthArray',
|
|
@@ -125,18 +115,17 @@ export const preferArrIsBoundedLengthArray: TSESLint.RuleModule<
|
|
|
125
115
|
min: minText,
|
|
126
116
|
max: maxText,
|
|
127
117
|
},
|
|
128
|
-
fix:
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
},
|
|
118
|
+
fix:
|
|
119
|
+
arr === undefined
|
|
120
|
+
? null
|
|
121
|
+
: (fixer) => {
|
|
122
|
+
const replacement = `${arr.localName}.isBoundedLengthArray(${minText}, ${maxText}, ${arrayText})`;
|
|
123
|
+
|
|
124
|
+
return [
|
|
125
|
+
...arr.edits(fixer),
|
|
126
|
+
fixer.replaceText(node, replacement),
|
|
127
|
+
];
|
|
128
|
+
},
|
|
140
129
|
});
|
|
141
130
|
}
|
|
142
131
|
},
|
|
@@ -1,17 +1,11 @@
|
|
|
1
1
|
import type { TSESLint, TSESTree } from '@typescript-eslint/utils';
|
|
2
|
-
import {
|
|
3
|
-
buildNamedImportFix,
|
|
4
|
-
getArgumentText,
|
|
5
|
-
getImportDeclarations,
|
|
6
|
-
getNamedImports,
|
|
7
|
-
skipTypeWrappers,
|
|
8
|
-
} from 'eslint-rule-forge';
|
|
2
|
+
import { getArgumentText, skipTypeWrappers } from 'eslint-rule-forge';
|
|
9
3
|
import {
|
|
10
4
|
asLengthAccess,
|
|
11
5
|
isArrayOrTupleExpression,
|
|
12
6
|
isIntegerLiteralOrConstant,
|
|
13
7
|
} from './ast-utils.mjs';
|
|
14
|
-
import {
|
|
8
|
+
import { tsDataForgeValueAt } from './import-binding.mjs';
|
|
15
9
|
|
|
16
10
|
type Options = readonly [];
|
|
17
11
|
|
|
@@ -39,13 +33,6 @@ export const preferArrIsFixedLengthArray: TSESLint.RuleModule<
|
|
|
39
33
|
create: (context) => {
|
|
40
34
|
const sourceCode = context.sourceCode;
|
|
41
35
|
|
|
42
|
-
const program = sourceCode.ast;
|
|
43
|
-
|
|
44
|
-
const tsDataForgeImports = getImportDeclarations(
|
|
45
|
-
program,
|
|
46
|
-
TS_DATA_FORGE_MODULE,
|
|
47
|
-
);
|
|
48
|
-
|
|
49
36
|
const services = context.sourceCode.parserServices;
|
|
50
37
|
|
|
51
38
|
const mut_nodesToFix: {
|
|
@@ -92,27 +79,29 @@ export const preferArrIsFixedLengthArray: TSESLint.RuleModule<
|
|
|
92
79
|
mut_nodesToFix.push({
|
|
93
80
|
node,
|
|
94
81
|
arrayExpression,
|
|
95
|
-
// The literal or constant itself: a wrapper such as `as number`
|
|
96
|
-
//
|
|
82
|
+
// The literal or constant itself: a wrapper such as `as number` would
|
|
83
|
+
// only widen the length the guard narrows to.
|
|
97
84
|
lengthExpression: skipTypeWrappers(valueSide),
|
|
98
85
|
isNegated,
|
|
99
86
|
});
|
|
100
87
|
},
|
|
101
88
|
'Program:exit': () => {
|
|
102
|
-
const
|
|
89
|
+
const arrAt = tsDataForgeValueAt(sourceCode, 'Arr');
|
|
103
90
|
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
91
|
+
for (const {
|
|
92
|
+
node,
|
|
93
|
+
arrayExpression,
|
|
94
|
+
lengthExpression,
|
|
95
|
+
isNegated,
|
|
96
|
+
} of mut_nodesToFix) {
|
|
110
97
|
const arrayText = getArgumentText(sourceCode, arrayExpression);
|
|
111
98
|
|
|
112
99
|
const lengthText = sourceCode.getText(lengthExpression);
|
|
113
100
|
|
|
114
101
|
const originalText = sourceCode.getText(node);
|
|
115
102
|
|
|
103
|
+
const arr = arrAt(node);
|
|
104
|
+
|
|
116
105
|
context.report({
|
|
117
106
|
node,
|
|
118
107
|
messageId: 'useIsFixedLengthArray',
|
|
@@ -121,20 +110,19 @@ export const preferArrIsFixedLengthArray: TSESLint.RuleModule<
|
|
|
121
110
|
arrayName: arrayText,
|
|
122
111
|
length: lengthText,
|
|
123
112
|
},
|
|
124
|
-
fix:
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
},
|
|
113
|
+
fix:
|
|
114
|
+
arr === undefined
|
|
115
|
+
? null
|
|
116
|
+
: (fixer) => {
|
|
117
|
+
const baseCall = `${arr.localName}.isFixedLengthArray(${lengthText}, ${arrayText})`;
|
|
118
|
+
|
|
119
|
+
const replacement = isNegated ? `!${baseCall}` : baseCall;
|
|
120
|
+
|
|
121
|
+
return [
|
|
122
|
+
...arr.edits(fixer),
|
|
123
|
+
fixer.replaceText(node, replacement),
|
|
124
|
+
];
|
|
125
|
+
},
|
|
138
126
|
});
|
|
139
127
|
}
|
|
140
128
|
},
|
|
@@ -158,13 +158,22 @@ describe('prefer-arr-is-fixed-length-array', () => {
|
|
|
158
158
|
const ok1 = xs.length === 3;
|
|
159
159
|
const ok2 = ys.length === 2;
|
|
160
160
|
`,
|
|
161
|
-
output:
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
161
|
+
output: [
|
|
162
|
+
dedent`
|
|
163
|
+
import { Arr } from 'ts-data-forge';
|
|
164
|
+
const xs = [1, 2, 3];
|
|
165
|
+
const ys = [4, 5];
|
|
166
|
+
const ok1 = Arr.isFixedLengthArray(3, xs);
|
|
167
|
+
const ok2 = ys.length === 2;
|
|
168
|
+
`,
|
|
169
|
+
dedent`
|
|
170
|
+
import { Arr } from 'ts-data-forge';
|
|
171
|
+
const xs = [1, 2, 3];
|
|
172
|
+
const ys = [4, 5];
|
|
173
|
+
const ok1 = Arr.isFixedLengthArray(3, xs);
|
|
174
|
+
const ok2 = Arr.isFixedLengthArray(2, ys);
|
|
175
|
+
`,
|
|
176
|
+
],
|
|
168
177
|
errors: [
|
|
169
178
|
{ messageId: 'useIsFixedLengthArray' },
|
|
170
179
|
{ messageId: 'useIsFixedLengthArray' },
|
|
@@ -1,18 +1,12 @@
|
|
|
1
1
|
import type { TSESLint, TSESTree } from '@typescript-eslint/utils';
|
|
2
|
-
import {
|
|
3
|
-
buildNamedImportFix,
|
|
4
|
-
getArgumentText,
|
|
5
|
-
getImportDeclarations,
|
|
6
|
-
getNamedImports,
|
|
7
|
-
skipTypeWrappers,
|
|
8
|
-
} from 'eslint-rule-forge';
|
|
2
|
+
import { getArgumentText, skipTypeWrappers } from 'eslint-rule-forge';
|
|
9
3
|
import {
|
|
10
4
|
asLengthAccess,
|
|
11
5
|
isArrayOrTupleExpression,
|
|
12
6
|
isIntegerLiteralOrConstant,
|
|
13
7
|
isPartOfBoundedLengthCheck,
|
|
14
8
|
} from './ast-utils.mjs';
|
|
15
|
-
import {
|
|
9
|
+
import { tsDataForgeValueAt } from './import-binding.mjs';
|
|
16
10
|
|
|
17
11
|
type Options = readonly [];
|
|
18
12
|
|
|
@@ -40,13 +34,6 @@ export const preferArrIsMaxLengthArray: TSESLint.RuleModule<
|
|
|
40
34
|
create: (context) => {
|
|
41
35
|
const sourceCode = context.sourceCode;
|
|
42
36
|
|
|
43
|
-
const program = sourceCode.ast;
|
|
44
|
-
|
|
45
|
-
const tsDataForgeImports = getImportDeclarations(
|
|
46
|
-
program,
|
|
47
|
-
TS_DATA_FORGE_MODULE,
|
|
48
|
-
);
|
|
49
|
-
|
|
50
37
|
const services = context.sourceCode.parserServices;
|
|
51
38
|
|
|
52
39
|
const mut_nodesToFix: {
|
|
@@ -98,26 +85,27 @@ export const preferArrIsMaxLengthArray: TSESLint.RuleModule<
|
|
|
98
85
|
mut_nodesToFix.push({
|
|
99
86
|
node,
|
|
100
87
|
arrayExpression,
|
|
101
|
-
// The literal or constant itself: a wrapper such as `as number`
|
|
102
|
-
//
|
|
88
|
+
// The literal or constant itself: a wrapper such as `as number` would
|
|
89
|
+
// only widen the length the guard narrows to.
|
|
103
90
|
lengthExpression: skipTypeWrappers(valueSide),
|
|
104
91
|
});
|
|
105
92
|
},
|
|
106
93
|
'Program:exit': () => {
|
|
107
|
-
const
|
|
94
|
+
const arrAt = tsDataForgeValueAt(sourceCode, 'Arr');
|
|
108
95
|
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
] of mut_nodesToFix.entries()) {
|
|
96
|
+
for (const {
|
|
97
|
+
node,
|
|
98
|
+
arrayExpression,
|
|
99
|
+
lengthExpression,
|
|
100
|
+
} of mut_nodesToFix) {
|
|
115
101
|
const arrayText = getArgumentText(sourceCode, arrayExpression);
|
|
116
102
|
|
|
117
103
|
const lengthText = sourceCode.getText(lengthExpression);
|
|
118
104
|
|
|
119
105
|
const originalText = sourceCode.getText(node);
|
|
120
106
|
|
|
107
|
+
const arr = arrAt(node);
|
|
108
|
+
|
|
121
109
|
context.report({
|
|
122
110
|
node,
|
|
123
111
|
messageId: 'useIsMaxLengthArray',
|
|
@@ -126,18 +114,17 @@ export const preferArrIsMaxLengthArray: TSESLint.RuleModule<
|
|
|
126
114
|
arrayName: arrayText,
|
|
127
115
|
length: lengthText,
|
|
128
116
|
},
|
|
129
|
-
fix:
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
},
|
|
117
|
+
fix:
|
|
118
|
+
arr === undefined
|
|
119
|
+
? null
|
|
120
|
+
: (fixer) => {
|
|
121
|
+
const replacement = `${arr.localName}.isMaxLengthArray(${lengthText}, ${arrayText})`;
|
|
122
|
+
|
|
123
|
+
return [
|
|
124
|
+
...arr.edits(fixer),
|
|
125
|
+
fixer.replaceText(node, replacement),
|
|
126
|
+
];
|
|
127
|
+
},
|
|
141
128
|
});
|
|
142
129
|
}
|
|
143
130
|
},
|
|
@@ -171,13 +171,22 @@ describe('prefer-arr-is-max-length-array', () => {
|
|
|
171
171
|
const ok1 = xs.length <= 2;
|
|
172
172
|
const ok2 = ys.length <= 1;
|
|
173
173
|
`,
|
|
174
|
-
output:
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
174
|
+
output: [
|
|
175
|
+
dedent`
|
|
176
|
+
import { Arr } from 'ts-data-forge';
|
|
177
|
+
const xs = [1, 2, 3];
|
|
178
|
+
const ys = [4, 5];
|
|
179
|
+
const ok1 = Arr.isMaxLengthArray(2, xs);
|
|
180
|
+
const ok2 = ys.length <= 1;
|
|
181
|
+
`,
|
|
182
|
+
dedent`
|
|
183
|
+
import { Arr } from 'ts-data-forge';
|
|
184
|
+
const xs = [1, 2, 3];
|
|
185
|
+
const ys = [4, 5];
|
|
186
|
+
const ok1 = Arr.isMaxLengthArray(2, xs);
|
|
187
|
+
const ok2 = Arr.isMaxLengthArray(1, ys);
|
|
188
|
+
`,
|
|
189
|
+
],
|
|
181
190
|
errors: [
|
|
182
191
|
{ messageId: 'useIsMaxLengthArray' },
|
|
183
192
|
{ messageId: 'useIsMaxLengthArray' },
|
|
@@ -1,18 +1,12 @@
|
|
|
1
1
|
import type { TSESLint, TSESTree } from '@typescript-eslint/utils';
|
|
2
|
-
import {
|
|
3
|
-
buildNamedImportFix,
|
|
4
|
-
getArgumentText,
|
|
5
|
-
getImportDeclarations,
|
|
6
|
-
getNamedImports,
|
|
7
|
-
skipTypeWrappers,
|
|
8
|
-
} from 'eslint-rule-forge';
|
|
2
|
+
import { getArgumentText, skipTypeWrappers } from 'eslint-rule-forge';
|
|
9
3
|
import {
|
|
10
4
|
asLengthAccess,
|
|
11
5
|
isArrayOrTupleExpression,
|
|
12
6
|
isIntegerLiteralOrConstant,
|
|
13
7
|
isPartOfBoundedLengthCheck,
|
|
14
8
|
} from './ast-utils.mjs';
|
|
15
|
-
import {
|
|
9
|
+
import { tsDataForgeValueAt } from './import-binding.mjs';
|
|
16
10
|
|
|
17
11
|
type Options = readonly [];
|
|
18
12
|
|
|
@@ -40,13 +34,6 @@ export const preferArrIsMinLengthArray: TSESLint.RuleModule<
|
|
|
40
34
|
create: (context) => {
|
|
41
35
|
const sourceCode = context.sourceCode;
|
|
42
36
|
|
|
43
|
-
const program = sourceCode.ast;
|
|
44
|
-
|
|
45
|
-
const tsDataForgeImports = getImportDeclarations(
|
|
46
|
-
program,
|
|
47
|
-
TS_DATA_FORGE_MODULE,
|
|
48
|
-
);
|
|
49
|
-
|
|
50
37
|
const services = context.sourceCode.parserServices;
|
|
51
38
|
|
|
52
39
|
const mut_nodesToFix: {
|
|
@@ -98,26 +85,27 @@ export const preferArrIsMinLengthArray: TSESLint.RuleModule<
|
|
|
98
85
|
mut_nodesToFix.push({
|
|
99
86
|
node,
|
|
100
87
|
arrayExpression,
|
|
101
|
-
// The literal or constant itself: a wrapper such as `as number`
|
|
102
|
-
//
|
|
88
|
+
// The literal or constant itself: a wrapper such as `as number` would
|
|
89
|
+
// only widen the length the guard narrows to.
|
|
103
90
|
lengthExpression: skipTypeWrappers(valueSide),
|
|
104
91
|
});
|
|
105
92
|
},
|
|
106
93
|
'Program:exit': () => {
|
|
107
|
-
const
|
|
94
|
+
const arrAt = tsDataForgeValueAt(sourceCode, 'Arr');
|
|
108
95
|
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
] of mut_nodesToFix.entries()) {
|
|
96
|
+
for (const {
|
|
97
|
+
node,
|
|
98
|
+
arrayExpression,
|
|
99
|
+
lengthExpression,
|
|
100
|
+
} of mut_nodesToFix) {
|
|
115
101
|
const arrayText = getArgumentText(sourceCode, arrayExpression);
|
|
116
102
|
|
|
117
103
|
const lengthText = sourceCode.getText(lengthExpression);
|
|
118
104
|
|
|
119
105
|
const originalText = sourceCode.getText(node);
|
|
120
106
|
|
|
107
|
+
const arr = arrAt(node);
|
|
108
|
+
|
|
121
109
|
context.report({
|
|
122
110
|
node,
|
|
123
111
|
messageId: 'useIsMinLengthArray',
|
|
@@ -126,18 +114,17 @@ export const preferArrIsMinLengthArray: TSESLint.RuleModule<
|
|
|
126
114
|
arrayName: arrayText,
|
|
127
115
|
length: lengthText,
|
|
128
116
|
},
|
|
129
|
-
fix:
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
},
|
|
117
|
+
fix:
|
|
118
|
+
arr === undefined
|
|
119
|
+
? null
|
|
120
|
+
: (fixer) => {
|
|
121
|
+
const replacement = `${arr.localName}.isMinLengthArray(${lengthText}, ${arrayText})`;
|
|
122
|
+
|
|
123
|
+
return [
|
|
124
|
+
...arr.edits(fixer),
|
|
125
|
+
fixer.replaceText(node, replacement),
|
|
126
|
+
];
|
|
127
|
+
},
|
|
141
128
|
});
|
|
142
129
|
}
|
|
143
130
|
},
|
|
@@ -172,13 +172,22 @@ describe('prefer-arr-is-min-length-array', () => {
|
|
|
172
172
|
const ok1 = xs.length >= 2;
|
|
173
173
|
const ok2 = ys.length >= 1;
|
|
174
174
|
`,
|
|
175
|
-
output:
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
175
|
+
output: [
|
|
176
|
+
dedent`
|
|
177
|
+
import { Arr } from 'ts-data-forge';
|
|
178
|
+
const xs = [1, 2, 3];
|
|
179
|
+
const ys = [4, 5];
|
|
180
|
+
const ok1 = Arr.isMinLengthArray(2, xs);
|
|
181
|
+
const ok2 = ys.length >= 1;
|
|
182
|
+
`,
|
|
183
|
+
dedent`
|
|
184
|
+
import { Arr } from 'ts-data-forge';
|
|
185
|
+
const xs = [1, 2, 3];
|
|
186
|
+
const ys = [4, 5];
|
|
187
|
+
const ok1 = Arr.isMinLengthArray(2, xs);
|
|
188
|
+
const ok2 = Arr.isMinLengthArray(1, ys);
|
|
189
|
+
`,
|
|
190
|
+
],
|
|
182
191
|
errors: [
|
|
183
192
|
{ messageId: 'useIsMinLengthArray' },
|
|
184
193
|
{ messageId: 'useIsMinLengthArray' },
|
|
@@ -3,15 +3,9 @@ import {
|
|
|
3
3
|
type TSESLint,
|
|
4
4
|
type TSESTree,
|
|
5
5
|
} from '@typescript-eslint/utils';
|
|
6
|
-
import {
|
|
7
|
-
buildNamedImportFix,
|
|
8
|
-
getArgumentText,
|
|
9
|
-
getImportDeclarations,
|
|
10
|
-
getNamedImports,
|
|
11
|
-
skipTypeWrappers,
|
|
12
|
-
} from 'eslint-rule-forge';
|
|
6
|
+
import { getArgumentText, skipTypeWrappers } from 'eslint-rule-forge';
|
|
13
7
|
import { asLengthAccess, isArrayOrTupleExpression } from './ast-utils.mjs';
|
|
14
|
-
import {
|
|
8
|
+
import { tsDataForgeValueAt } from './import-binding.mjs';
|
|
15
9
|
|
|
16
10
|
type Options = readonly [];
|
|
17
11
|
|
|
@@ -36,13 +30,6 @@ export const preferArrIsNonEmpty: TSESLint.RuleModule<MessageIds, Options> = {
|
|
|
36
30
|
create: (context) => {
|
|
37
31
|
const sourceCode = context.sourceCode;
|
|
38
32
|
|
|
39
|
-
const program = sourceCode.ast;
|
|
40
|
-
|
|
41
|
-
const tsDataForgeImports = getImportDeclarations(
|
|
42
|
-
program,
|
|
43
|
-
TS_DATA_FORGE_MODULE,
|
|
44
|
-
);
|
|
45
|
-
|
|
46
33
|
const services = context.sourceCode.parserServices;
|
|
47
34
|
|
|
48
35
|
const mut_nodesToFix: {
|
|
@@ -90,18 +77,15 @@ export const preferArrIsNonEmpty: TSESLint.RuleModule<MessageIds, Options> = {
|
|
|
90
77
|
});
|
|
91
78
|
},
|
|
92
79
|
'Program:exit': () => {
|
|
93
|
-
const
|
|
94
|
-
|
|
95
|
-
const hasArrImport = namedImports.includes('Arr');
|
|
80
|
+
const arrAt = tsDataForgeValueAt(sourceCode, 'Arr');
|
|
96
81
|
|
|
97
|
-
for (const
|
|
98
|
-
index,
|
|
99
|
-
{ node, arrayExpression },
|
|
100
|
-
] of mut_nodesToFix.entries()) {
|
|
82
|
+
for (const { node, arrayExpression } of mut_nodesToFix) {
|
|
101
83
|
const arrayText = getArgumentText(sourceCode, arrayExpression);
|
|
102
84
|
|
|
103
85
|
const originalText = sourceCode.getText(node);
|
|
104
86
|
|
|
87
|
+
const arr = arrAt(node);
|
|
88
|
+
|
|
105
89
|
context.report({
|
|
106
90
|
node,
|
|
107
91
|
messageId: 'useIsNonEmpty',
|
|
@@ -109,18 +93,17 @@ export const preferArrIsNonEmpty: TSESLint.RuleModule<MessageIds, Options> = {
|
|
|
109
93
|
original: originalText,
|
|
110
94
|
arrayName: arrayText,
|
|
111
95
|
},
|
|
112
|
-
fix:
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
},
|
|
96
|
+
fix:
|
|
97
|
+
arr === undefined
|
|
98
|
+
? null
|
|
99
|
+
: (fixer) => {
|
|
100
|
+
const replacement = `${arr.localName}.isNonEmpty(${arrayText})`;
|
|
101
|
+
|
|
102
|
+
return [
|
|
103
|
+
...arr.edits(fixer),
|
|
104
|
+
fixer.replaceText(node, replacement),
|
|
105
|
+
];
|
|
106
|
+
},
|
|
124
107
|
});
|
|
125
108
|
}
|
|
126
109
|
},
|