eslint-plugin-ts-data-forge 0.8.4 → 0.8.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 +0 -32
- package/dist/rules/ast-utils.d.mts.map +1 -1
- package/dist/rules/ast-utils.mjs +4 -56
- package/dist/rules/ast-utils.mjs.map +1 -1
- package/dist/rules/no-unnecessary-type-guard.d.mts.map +1 -1
- package/dist/rules/no-unnecessary-type-guard.mjs +6 -6
- package/dist/rules/no-unnecessary-type-guard.mjs.map +1 -1
- package/dist/rules/prefer-arr-is-array.d.mts.map +1 -1
- package/dist/rules/prefer-arr-is-array.mjs +7 -5
- package/dist/rules/prefer-arr-is-array.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 +9 -6
- 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 +9 -6
- 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 +9 -6
- 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 +9 -6
- 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 +9 -6
- 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 +8 -11
- 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 +8 -6
- 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 +11 -18
- 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 +6 -8
- 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 +10 -6
- package/dist/rules/prefer-canonical-array-slicing.mjs.map +1 -1
- package/dist/rules/prefer-canonical-length-cast.d.mts.map +1 -1
- package/dist/rules/prefer-canonical-length-cast.mjs +3 -3
- package/dist/rules/prefer-canonical-length-cast.mjs.map +1 -1
- package/dist/rules/prefer-canonical-length-guard.d.mts.map +1 -1
- package/dist/rules/prefer-canonical-length-guard.mjs +4 -4
- package/dist/rules/prefer-canonical-length-guard.mjs.map +1 -1
- package/dist/rules/prefer-comparison-over-nullish-guard.d.mts.map +1 -1
- package/dist/rules/prefer-comparison-over-nullish-guard.mjs +3 -2
- package/dist/rules/prefer-comparison-over-nullish-guard.mjs.map +1 -1
- package/dist/rules/prefer-is-non-null-object.d.mts.map +1 -1
- package/dist/rules/prefer-is-non-null-object.mjs +5 -5
- package/dist/rules/prefer-is-non-null-object.mjs.map +1 -1
- package/dist/rules/prefer-is-record-and-has-key.d.mts.map +1 -1
- package/dist/rules/prefer-is-record-and-has-key.mjs +5 -5
- package/dist/rules/prefer-is-record-and-has-key.mjs.map +1 -1
- package/dist/rules/prefer-num-safe-parse-float.d.mts.map +1 -1
- package/dist/rules/prefer-num-safe-parse-float.mjs +6 -6
- package/dist/rules/prefer-num-safe-parse-float.mjs.map +1 -1
- package/dist/rules/prefer-num-safe-parse-int.d.mts.map +1 -1
- package/dist/rules/prefer-num-safe-parse-int.mjs +6 -6
- package/dist/rules/prefer-num-safe-parse-int.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 +9 -12
- package/dist/rules/prefer-obj-over-entries-round-trip.mjs.map +1 -1
- package/dist/rules/prefer-range-for-loop.d.mts.map +1 -1
- package/dist/rules/prefer-range-for-loop.mjs +8 -8
- package/dist/rules/prefer-range-for-loop.mjs.map +1 -1
- package/package.json +10 -9
- package/src/rules/ast-utils.mts +8 -82
- package/src/rules/no-unnecessary-type-guard.mts +14 -10
- package/src/rules/prefer-arr-is-array.mts +14 -7
- package/src/rules/prefer-arr-is-array.test.mts +14 -0
- package/src/rules/prefer-arr-is-bounded-length-array.mts +16 -10
- package/src/rules/prefer-arr-is-fixed-length-array.mts +17 -11
- package/src/rules/prefer-arr-is-max-length-array.mts +17 -11
- package/src/rules/prefer-arr-is-min-length-array.mts +17 -11
- package/src/rules/prefer-arr-is-non-empty.mts +16 -13
- package/src/rules/prefer-arr-scan.mts +24 -19
- package/src/rules/prefer-arr-sum.mts +18 -14
- package/src/rules/prefer-arr-uniq.mts +24 -28
- package/src/rules/prefer-as-int.mts +19 -12
- package/src/rules/prefer-canonical-array-slicing.mts +22 -12
- package/src/rules/prefer-canonical-length-cast.mts +7 -3
- package/src/rules/prefer-canonical-length-guard.mts +9 -4
- package/src/rules/prefer-comparison-over-nullish-guard.mts +3 -2
- package/src/rules/prefer-comparison-over-nullish-guard.test.mts +16 -0
- package/src/rules/prefer-is-non-null-object.mts +11 -7
- package/src/rules/prefer-is-record-and-has-key.mts +14 -10
- package/src/rules/prefer-num-safe-parse-float.mts +15 -10
- package/src/rules/prefer-num-safe-parse-int.mts +15 -13
- package/src/rules/prefer-obj-over-entries-round-trip.mts +19 -22
- package/src/rules/prefer-range-for-loop.mts +16 -11
- package/dist/rules/import-utils.d.mts +0 -30
- package/dist/rules/import-utils.d.mts.map +0 -1
- package/dist/rules/import-utils.mjs +0 -98
- package/dist/rules/import-utils.mjs.map +0 -1
- package/src/rules/import-utils.mts +0 -175
|
@@ -3,13 +3,15 @@ import {
|
|
|
3
3
|
type TSESLint,
|
|
4
4
|
type TSESTree,
|
|
5
5
|
} from '@typescript-eslint/utils';
|
|
6
|
-
import * as ts from 'typescript';
|
|
7
|
-
import { toArgumentText, typeWrapperLayers } from './ast-utils.mjs';
|
|
8
6
|
import {
|
|
9
|
-
|
|
7
|
+
buildNamedImportFix,
|
|
8
|
+
getArgumentText,
|
|
9
|
+
getImportDeclarations,
|
|
10
10
|
getNamedImports,
|
|
11
|
-
|
|
12
|
-
} from '
|
|
11
|
+
typeWrapperLayers,
|
|
12
|
+
} from 'eslint-rule-forge';
|
|
13
|
+
import * as ts from 'typescript';
|
|
14
|
+
import { TS_DATA_FORGE_MODULE } from './constants.mjs';
|
|
13
15
|
|
|
14
16
|
type Options = readonly [];
|
|
15
17
|
|
|
@@ -62,7 +64,10 @@ export const preferNumSafeParseFloat: TSESLint.RuleModule<MessageIds, Options> =
|
|
|
62
64
|
|
|
63
65
|
const program = sourceCode.ast;
|
|
64
66
|
|
|
65
|
-
const
|
|
67
|
+
const tsDataForgeImports = getImportDeclarations(
|
|
68
|
+
program,
|
|
69
|
+
TS_DATA_FORGE_MODULE,
|
|
70
|
+
);
|
|
66
71
|
|
|
67
72
|
const services = context.sourceCode.parserServices;
|
|
68
73
|
|
|
@@ -145,7 +150,7 @@ export const preferNumSafeParseFloat: TSESLint.RuleModule<MessageIds, Options> =
|
|
|
145
150
|
mut_nodesToFix.push({ node, argExpression: firstArg });
|
|
146
151
|
},
|
|
147
152
|
'Program:exit': () => {
|
|
148
|
-
const namedImports = getNamedImports(
|
|
153
|
+
const namedImports = getNamedImports(tsDataForgeImports);
|
|
149
154
|
|
|
150
155
|
const missingImports = (['Num', 'Result'] as const).filter(
|
|
151
156
|
(name) => !namedImports.includes(name),
|
|
@@ -155,7 +160,7 @@ export const preferNumSafeParseFloat: TSESLint.RuleModule<MessageIds, Options> =
|
|
|
155
160
|
index,
|
|
156
161
|
{ node, argExpression },
|
|
157
162
|
] of mut_nodesToFix.entries()) {
|
|
158
|
-
const argText =
|
|
163
|
+
const argText = getArgumentText(sourceCode, argExpression);
|
|
159
164
|
|
|
160
165
|
const originalText = sourceCode.getText(node);
|
|
161
166
|
|
|
@@ -171,10 +176,10 @@ export const preferNumSafeParseFloat: TSESLint.RuleModule<MessageIds, Options> =
|
|
|
171
176
|
|
|
172
177
|
const importFixes =
|
|
173
178
|
index === 0 && missingImports.length > 0
|
|
174
|
-
?
|
|
179
|
+
? buildNamedImportFix(
|
|
175
180
|
fixer,
|
|
176
181
|
program,
|
|
177
|
-
|
|
182
|
+
TS_DATA_FORGE_MODULE,
|
|
178
183
|
missingImports,
|
|
179
184
|
)
|
|
180
185
|
: [];
|
|
@@ -3,17 +3,16 @@ import {
|
|
|
3
3
|
type TSESLint,
|
|
4
4
|
type TSESTree,
|
|
5
5
|
} from '@typescript-eslint/utils';
|
|
6
|
-
import * as ts from 'typescript';
|
|
7
6
|
import {
|
|
7
|
+
buildNamedImportFix,
|
|
8
|
+
getArgumentText,
|
|
9
|
+
getImportDeclarations,
|
|
10
|
+
getNamedImports,
|
|
8
11
|
skipTypeWrappers,
|
|
9
|
-
toArgumentText,
|
|
10
12
|
typeWrapperLayers,
|
|
11
|
-
} from '
|
|
12
|
-
import
|
|
13
|
-
|
|
14
|
-
getNamedImports,
|
|
15
|
-
getTsDataForgeImport,
|
|
16
|
-
} from './import-utils.mjs';
|
|
13
|
+
} from 'eslint-rule-forge';
|
|
14
|
+
import * as ts from 'typescript';
|
|
15
|
+
import { TS_DATA_FORGE_MODULE } from './constants.mjs';
|
|
17
16
|
|
|
18
17
|
type Options = readonly [];
|
|
19
18
|
|
|
@@ -63,7 +62,10 @@ export const preferNumSafeParseInt: TSESLint.RuleModule<MessageIds, Options> = {
|
|
|
63
62
|
|
|
64
63
|
const program = sourceCode.ast;
|
|
65
64
|
|
|
66
|
-
const
|
|
65
|
+
const tsDataForgeImports = getImportDeclarations(
|
|
66
|
+
program,
|
|
67
|
+
TS_DATA_FORGE_MODULE,
|
|
68
|
+
);
|
|
67
69
|
|
|
68
70
|
const services = context.sourceCode.parserServices;
|
|
69
71
|
|
|
@@ -147,7 +149,7 @@ export const preferNumSafeParseInt: TSESLint.RuleModule<MessageIds, Options> = {
|
|
|
147
149
|
mut_nodesToFix.push({ node, argExpression: firstArg });
|
|
148
150
|
},
|
|
149
151
|
'Program:exit': () => {
|
|
150
|
-
const namedImports = getNamedImports(
|
|
152
|
+
const namedImports = getNamedImports(tsDataForgeImports);
|
|
151
153
|
|
|
152
154
|
const missingImports = (['Num', 'Result'] as const).filter(
|
|
153
155
|
(name) => !namedImports.includes(name),
|
|
@@ -157,7 +159,7 @@ export const preferNumSafeParseInt: TSESLint.RuleModule<MessageIds, Options> = {
|
|
|
157
159
|
index,
|
|
158
160
|
{ node, argExpression },
|
|
159
161
|
] of mut_nodesToFix.entries()) {
|
|
160
|
-
const argText =
|
|
162
|
+
const argText = getArgumentText(sourceCode, argExpression);
|
|
161
163
|
|
|
162
164
|
const originalText = sourceCode.getText(node);
|
|
163
165
|
|
|
@@ -173,10 +175,10 @@ export const preferNumSafeParseInt: TSESLint.RuleModule<MessageIds, Options> = {
|
|
|
173
175
|
|
|
174
176
|
const importFixes =
|
|
175
177
|
index === 0 && missingImports.length > 0
|
|
176
|
-
?
|
|
178
|
+
? buildNamedImportFix(
|
|
177
179
|
fixer,
|
|
178
180
|
program,
|
|
179
|
-
|
|
181
|
+
TS_DATA_FORGE_MODULE,
|
|
180
182
|
missingImports,
|
|
181
183
|
)
|
|
182
184
|
: [];
|
|
@@ -3,14 +3,16 @@ import {
|
|
|
3
3
|
type TSESLint,
|
|
4
4
|
type TSESTree,
|
|
5
5
|
} from '@typescript-eslint/utils';
|
|
6
|
-
import { Arr } from 'ts-data-forge';
|
|
7
|
-
import type { ReadonlyRecord } from 'ts-type-forge';
|
|
8
6
|
import {
|
|
9
|
-
|
|
7
|
+
buildNamedImportFix,
|
|
8
|
+
getArgumentText,
|
|
9
|
+
getImportDeclarations,
|
|
10
10
|
getImportedLocalName,
|
|
11
11
|
getNamedImports,
|
|
12
|
-
|
|
13
|
-
} from '
|
|
12
|
+
} from 'eslint-rule-forge';
|
|
13
|
+
import { Arr } from 'ts-data-forge';
|
|
14
|
+
import type { ReadonlyRecord } from 'ts-type-forge';
|
|
15
|
+
import { TS_DATA_FORGE_MODULE } from './constants.mjs';
|
|
14
16
|
|
|
15
17
|
/* eslint-disable @typescript-eslint/prefer-readonly-parameter-types */
|
|
16
18
|
|
|
@@ -91,7 +93,10 @@ export const preferObjOverEntriesRoundTrip: TSESLint.RuleModule<
|
|
|
91
93
|
|
|
92
94
|
const program = sourceCode.ast;
|
|
93
95
|
|
|
94
|
-
const
|
|
96
|
+
const tsDataForgeImports = getImportDeclarations(
|
|
97
|
+
program,
|
|
98
|
+
TS_DATA_FORGE_MODULE,
|
|
99
|
+
);
|
|
95
100
|
|
|
96
101
|
const mut_roundTrips: {
|
|
97
102
|
node: TSESTree.CallExpression;
|
|
@@ -146,7 +151,7 @@ export const preferObjOverEntriesRoundTrip: TSESLint.RuleModule<
|
|
|
146
151
|
body.test,
|
|
147
152
|
);
|
|
148
153
|
|
|
149
|
-
const someText = `${optionalName}.some(${
|
|
154
|
+
const someText = `${optionalName}.some(${getArgumentText(sourceCode, body.kept)})`;
|
|
150
155
|
|
|
151
156
|
const noneText = `${optionalName}.none`;
|
|
152
157
|
|
|
@@ -167,12 +172,13 @@ export const preferObjOverEntriesRoundTrip: TSESLint.RuleModule<
|
|
|
167
172
|
},
|
|
168
173
|
|
|
169
174
|
'Program:exit': () => {
|
|
170
|
-
const namedImports = getNamedImports(
|
|
175
|
+
const namedImports = getNamedImports(tsDataForgeImports);
|
|
171
176
|
|
|
172
|
-
const objName =
|
|
177
|
+
const objName =
|
|
178
|
+
getImportedLocalName(tsDataForgeImports, 'Obj') ?? 'Obj';
|
|
173
179
|
|
|
174
180
|
const optionalName =
|
|
175
|
-
getImportedLocalName(
|
|
181
|
+
getImportedLocalName(tsDataForgeImports, 'Optional') ?? 'Optional';
|
|
176
182
|
|
|
177
183
|
const needsOptional = mut_roundTrips.some(
|
|
178
184
|
({ roundTrip }) => roundTrip.body.kind === 'optional',
|
|
@@ -191,19 +197,16 @@ export const preferObjOverEntriesRoundTrip: TSESLint.RuleModule<
|
|
|
191
197
|
node,
|
|
192
198
|
messageId: MESSAGE_ID_OF[roundTrip.method],
|
|
193
199
|
fix: (fixer) => {
|
|
194
|
-
const recordText =
|
|
195
|
-
sourceCode.getText(roundTrip.record),
|
|
196
|
-
roundTrip.record,
|
|
197
|
-
);
|
|
200
|
+
const recordText = getArgumentText(sourceCode, roundTrip.record);
|
|
198
201
|
|
|
199
202
|
const replacement = `${objName}.${roundTrip.method}(${recordText}, ${buildParams(roundTrip)} => ${buildCallbackBody(roundTrip, optionalName)})`;
|
|
200
203
|
|
|
201
204
|
const importFixes =
|
|
202
205
|
index === 0 && missingImports.length > 0
|
|
203
|
-
?
|
|
206
|
+
? buildNamedImportFix(
|
|
204
207
|
fixer,
|
|
205
208
|
program,
|
|
206
|
-
|
|
209
|
+
TS_DATA_FORGE_MODULE,
|
|
207
210
|
missingImports,
|
|
208
211
|
)
|
|
209
212
|
: [];
|
|
@@ -551,12 +554,6 @@ const conditionalTestText = (
|
|
|
551
554
|
): string =>
|
|
552
555
|
NEEDS_PARENS_AS_TEST.has(node.type) ? (`(${text})` as const) : text;
|
|
553
556
|
|
|
554
|
-
/** A comma expression would read as another argument without parentheses. */
|
|
555
|
-
const argumentText = (text: string, node: TSESTree.Expression): string =>
|
|
556
|
-
node.type === AST_NODE_TYPES.SequenceExpression
|
|
557
|
-
? (`(${text})` as const)
|
|
558
|
-
: text;
|
|
559
|
-
|
|
560
557
|
/**
|
|
561
558
|
* A concise arrow body cannot start with `{`, nor hold a bare comma. The text
|
|
562
559
|
* is what decides the first case rather than the node type, because an object
|
|
@@ -3,13 +3,15 @@ import {
|
|
|
3
3
|
type TSESLint,
|
|
4
4
|
type TSESTree,
|
|
5
5
|
} from '@typescript-eslint/utils';
|
|
6
|
-
import { Arr } from 'ts-data-forge';
|
|
7
|
-
import { skipTypeWrappers, toArgumentText } from './ast-utils.mjs';
|
|
8
6
|
import {
|
|
9
|
-
|
|
7
|
+
buildNamedImportFix,
|
|
8
|
+
getArgumentText,
|
|
9
|
+
getImportDeclarations,
|
|
10
10
|
getNamedImports,
|
|
11
|
-
|
|
12
|
-
} from '
|
|
11
|
+
skipTypeWrappers,
|
|
12
|
+
} from 'eslint-rule-forge';
|
|
13
|
+
import { Arr } from 'ts-data-forge';
|
|
14
|
+
import { TS_DATA_FORGE_MODULE } from './constants.mjs';
|
|
13
15
|
|
|
14
16
|
type Options = readonly [];
|
|
15
17
|
|
|
@@ -35,7 +37,10 @@ export const preferRangeForLoop: TSESLint.RuleModule<MessageIds, Options> = {
|
|
|
35
37
|
|
|
36
38
|
const program = sourceCode.ast;
|
|
37
39
|
|
|
38
|
-
const
|
|
40
|
+
const tsDataForgeImports = getImportDeclarations(
|
|
41
|
+
program,
|
|
42
|
+
TS_DATA_FORGE_MODULE,
|
|
43
|
+
);
|
|
39
44
|
|
|
40
45
|
const mut_nodesToFix: {
|
|
41
46
|
node: TSESTree.ForStatement;
|
|
@@ -128,15 +133,15 @@ export const preferRangeForLoop: TSESLint.RuleModule<MessageIds, Options> = {
|
|
|
128
133
|
}
|
|
129
134
|
} else {
|
|
130
135
|
// Variable step like i += step
|
|
131
|
-
mut_step =
|
|
136
|
+
mut_step = getArgumentText(sourceCode, node.update.right);
|
|
132
137
|
}
|
|
133
138
|
} else {
|
|
134
139
|
return;
|
|
135
140
|
}
|
|
136
141
|
|
|
137
|
-
const beginText =
|
|
142
|
+
const beginText = getArgumentText(sourceCode, beginExpr);
|
|
138
143
|
|
|
139
|
-
const endText =
|
|
144
|
+
const endText = getArgumentText(sourceCode, endExpr);
|
|
140
145
|
|
|
141
146
|
mut_nodesToFix.push({
|
|
142
147
|
node,
|
|
@@ -147,7 +152,7 @@ export const preferRangeForLoop: TSESLint.RuleModule<MessageIds, Options> = {
|
|
|
147
152
|
});
|
|
148
153
|
},
|
|
149
154
|
'Program:exit': () => {
|
|
150
|
-
const namedImports = getNamedImports(
|
|
155
|
+
const namedImports = getNamedImports(tsDataForgeImports);
|
|
151
156
|
|
|
152
157
|
const hasRangeImport = namedImports.includes('range');
|
|
153
158
|
|
|
@@ -175,7 +180,7 @@ export const preferRangeForLoop: TSESLint.RuleModule<MessageIds, Options> = {
|
|
|
175
180
|
|
|
176
181
|
const importFixes =
|
|
177
182
|
index === 0 && !hasRangeImport
|
|
178
|
-
?
|
|
183
|
+
? buildNamedImportFix(fixer, program, TS_DATA_FORGE_MODULE, [
|
|
179
184
|
'range',
|
|
180
185
|
])
|
|
181
186
|
: [];
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { type TSESLint, type TSESTree } from '@typescript-eslint/utils';
|
|
2
|
-
import type { DeepReadonly } from 'ts-type-forge';
|
|
3
|
-
export declare const getTsDataForgeImport: (program: TSESTree.Program) => TSESTree.ImportDeclaration | undefined;
|
|
4
|
-
export declare const getNamedImports: (node: DeepReadonly<TSESTree.ImportDeclaration> | undefined) => readonly string[];
|
|
5
|
-
/**
|
|
6
|
-
* Returns the in-scope local name a given canonical export is imported as
|
|
7
|
-
* (handling aliases such as `import { isX as y }` → `'y'`), or `undefined` when
|
|
8
|
-
* it is not imported. Used so autofixes reference the binding that actually
|
|
9
|
-
* exists rather than the canonical name.
|
|
10
|
-
*/
|
|
11
|
-
export declare const getImportedLocalName: (node: DeepReadonly<TSESTree.ImportDeclaration> | undefined, importedName: string) => string | undefined;
|
|
12
|
-
type ResolvedCallee = Readonly<{
|
|
13
|
-
/** The canonical (imported) ts-data-forge name, regardless of local alias. */
|
|
14
|
-
canonicalName: string;
|
|
15
|
-
/** The identifier node to rewrite when replacing the callee name. */
|
|
16
|
-
propertyNode: TSESTree.Node;
|
|
17
|
-
/** Whether the call was made through a namespace import (`tf.isX(...)`). */
|
|
18
|
-
isNamespace: boolean;
|
|
19
|
-
}>;
|
|
20
|
-
/**
|
|
21
|
-
* Builds a resolver that maps a call expression's callee to the canonical
|
|
22
|
-
* ts-data-forge function it refers to. Handles named imports (including aliases
|
|
23
|
-
* such as `import { isX as y }`) and namespace imports (`import * as tf` →
|
|
24
|
-
* `tf.isX(...)`). Returns `undefined` for any callee that does not reference the
|
|
25
|
-
* given ts-data-forge import.
|
|
26
|
-
*/
|
|
27
|
-
export declare const buildCalleeResolver: (importDecl: TSESTree.ImportDeclaration | undefined) => ((callee: DeepReadonly<TSESTree.Expression>) => ResolvedCallee | undefined);
|
|
28
|
-
export declare const buildImportFixes: (fixer: TSESLint.RuleFixer, program: TSESTree.Program, _tsDataForgeImport: TSESTree.ImportDeclaration | undefined, requiredNames: readonly string[]) => readonly TSESLint.RuleFix[];
|
|
29
|
-
export {};
|
|
30
|
-
//# sourceMappingURL=import-utils.d.mts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"import-utils.d.mts","sourceRoot":"","sources":["../../src/rules/import-utils.mts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,QAAQ,EACb,KAAK,QAAQ,EACd,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAMlD,eAAO,MAAM,oBAAoB,YACtB,QAAQ,CAAC,OAAO,KACxB,QAAQ,CAAC,iBAAiB,GAAG,SAK7B,CAAC;AAEJ,eAAO,MAAM,eAAe,SACpB,YAAY,CAAC,QAAQ,CAAC,iBAAiB,CAAC,GAAG,SAAS,KACzD,SAAS,MAAM,EAiBjB,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,SACzB,YAAY,CAAC,QAAQ,CAAC,iBAAiB,CAAC,GAAG,SAAS,gBAC5C,MAAM,KACnB,MAAM,GAAG,SAOG,CAAC;AAEhB,KAAK,cAAc,GAAG,QAAQ,CAAC;IAC7B,8EAA8E;IAC9E,aAAa,EAAE,MAAM,CAAC;IACtB,qEAAqE;IACrE,YAAY,EAAE,QAAQ,CAAC,IAAI,CAAC;IAC5B,4EAA4E;IAC5E,WAAW,EAAE,OAAO,CAAC;CACtB,CAAC,CAAC;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,eAClB,QAAQ,CAAC,iBAAiB,GAAG,SAAS,KACjD,CAAC,CACF,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC,UAAU,CAAC,KACtC,cAAc,GAAG,SAAS,CAsE9B,CAAC;AAOF,eAAO,MAAM,gBAAgB,UACpB,QAAQ,CAAC,SAAS,WAChB,QAAQ,CAAC,OAAO,sBACL,QAAQ,CAAC,iBAAiB,GAAG,SAAS,iBAC3C,SAAS,MAAM,EAAE,KAC/B,SAAS,QAAQ,CAAC,OAAO,EAa3B,CAAC"}
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
import { AST_NODE_TYPES, } from '@typescript-eslint/utils';
|
|
2
|
-
import { isTypeWrapper } from './ast-utils.mjs';
|
|
3
|
-
import { TS_DATA_FORGE_MODULE } from './constants.mjs';
|
|
4
|
-
|
|
5
|
-
export const getTsDataForgeImport = (program) => program.body.find((node) => node.type === AST_NODE_TYPES.ImportDeclaration &&
|
|
6
|
-
node.source.value === TS_DATA_FORGE_MODULE);
|
|
7
|
-
export const getNamedImports = (node) => {
|
|
8
|
-
if (node === undefined) {
|
|
9
|
-
return [];
|
|
10
|
-
}
|
|
11
|
-
return node.specifiers.flatMap((specifier) => specifier.type === AST_NODE_TYPES.ImportSpecifier
|
|
12
|
-
? (() => {
|
|
13
|
-
const importedName = specifier.imported.type === AST_NODE_TYPES.Identifier
|
|
14
|
-
? specifier.imported.name
|
|
15
|
-
: specifier.imported.value;
|
|
16
|
-
return typeof importedName === 'string' ? [importedName] : [];
|
|
17
|
-
})()
|
|
18
|
-
: []);
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
export const getImportedLocalName = (node, importedName) => node?.specifiers.find((specifier) => specifier.type === AST_NODE_TYPES.ImportSpecifier &&
|
|
27
|
-
(specifier.imported.type === AST_NODE_TYPES.Identifier
|
|
28
|
-
? specifier.imported.name
|
|
29
|
-
: specifier.imported.value) === importedName)?.local.name;
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
export const buildCalleeResolver = (importDecl) => {
|
|
38
|
-
const specifiers = importDecl?.specifiers ?? [];
|
|
39
|
-
const namespaceName = specifiers.find((specifier) => specifier.type === AST_NODE_TYPES.ImportNamespaceSpecifier)?.local.name;
|
|
40
|
-
const localToCanonical = new Map(specifiers.flatMap((specifier) => {
|
|
41
|
-
if (specifier.type !== AST_NODE_TYPES.ImportSpecifier) {
|
|
42
|
-
return [];
|
|
43
|
-
}
|
|
44
|
-
const importedName = specifier.imported.type === AST_NODE_TYPES.Identifier
|
|
45
|
-
? specifier.imported.name
|
|
46
|
-
: specifier.imported.value;
|
|
47
|
-
return typeof importedName === 'string'
|
|
48
|
-
? [[specifier.local.name, importedName]]
|
|
49
|
-
: [];
|
|
50
|
-
}));
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
const resolve = (callee) => {
|
|
55
|
-
if (isTypeWrapper(callee)) {
|
|
56
|
-
return resolve(callee.expression);
|
|
57
|
-
}
|
|
58
|
-
if (callee.type === AST_NODE_TYPES.Identifier) {
|
|
59
|
-
const canonicalName = localToCanonical.get(callee.name);
|
|
60
|
-
return canonicalName === undefined
|
|
61
|
-
? undefined
|
|
62
|
-
: {
|
|
63
|
-
canonicalName,
|
|
64
|
-
|
|
65
|
-
propertyNode: callee,
|
|
66
|
-
isNamespace: false,
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
if (namespaceName === undefined ||
|
|
70
|
-
callee.type !== AST_NODE_TYPES.MemberExpression ||
|
|
71
|
-
callee.computed ||
|
|
72
|
-
callee.property.type !== AST_NODE_TYPES.Identifier) {
|
|
73
|
-
return undefined;
|
|
74
|
-
}
|
|
75
|
-
const object = skipReadonlyTypeWrappers(callee.object);
|
|
76
|
-
return object.type === AST_NODE_TYPES.Identifier &&
|
|
77
|
-
object.name === namespaceName
|
|
78
|
-
? {
|
|
79
|
-
canonicalName: callee.property.name,
|
|
80
|
-
|
|
81
|
-
propertyNode: callee.property,
|
|
82
|
-
isNamespace: true,
|
|
83
|
-
}
|
|
84
|
-
: undefined;
|
|
85
|
-
};
|
|
86
|
-
return resolve;
|
|
87
|
-
};
|
|
88
|
-
const skipReadonlyTypeWrappers = (node) => isTypeWrapper(node) ? skipReadonlyTypeWrappers(node.expression) : node;
|
|
89
|
-
export const buildImportFixes = (fixer, program, _tsDataForgeImport, requiredNames) => {
|
|
90
|
-
const specifierText = requiredNames.join(', ');
|
|
91
|
-
const importStatement = `import { ${specifierText} } from '${TS_DATA_FORGE_MODULE}';`;
|
|
92
|
-
const newLine = '\n';
|
|
93
|
-
const insertionText = `${importStatement}${newLine}`;
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
return [fixer.insertTextBefore(program, insertionText)];
|
|
97
|
-
};
|
|
98
|
-
//# sourceMappingURL=import-utils.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"import-utils.mjs","sourceRoot":"","sources":["../../src/rules/import-utils.mts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,GAGf,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAEvD,uEAAuE;AAEvE,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAClC,OAAyB,EACe,EAAE,CAC1C,OAAO,CAAC,IAAI,CAAC,IAAI,CACf,CAAC,IAAI,EAAsC,EAAE,CAC3C,IAAI,CAAC,IAAI,KAAK,cAAc,CAAC,iBAAiB;IAC9C,IAAI,CAAC,MAAM,CAAC,KAAK,KAAK,oBAAoB,CAC7C,CAAC;AAEJ,MAAM,CAAC,MAAM,eAAe,GAAG,CAC7B,IAA0D,EACvC,EAAE;IACrB,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,OAAO,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,SAAS,EAAE,EAAE,CAC3C,SAAS,CAAC,IAAI,KAAK,cAAc,CAAC,eAAe;QAC/C,CAAC,CAAC,CAAC,GAAG,EAAE;YACJ,MAAM,YAAY,GAChB,SAAS,CAAC,QAAQ,CAAC,IAAI,KAAK,cAAc,CAAC,UAAU;gBACnD,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI;gBACzB,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC;YAE/B,OAAO,OAAO,YAAY,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAChE,CAAC,CAAC,EAAE;QACN,CAAC,CAAC,EAAE,CACP,CAAC;AACJ,CAAC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAClC,IAA0D,EAC1D,YAAoB,EACA,EAAE,CACtB,IAAI,EAAE,UAAU,CAAC,IAAI,CACnB,CAAC,SAAS,EAAE,EAAE,CACZ,SAAS,CAAC,IAAI,KAAK,cAAc,CAAC,eAAe;IACjD,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,KAAK,cAAc,CAAC,UAAU;QACpD,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI;QACzB,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,YAAY,CACjD,EAAE,KAAK,CAAC,IAAI,CAAC;AAWhB;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CACjC,UAAkD,EAGnB,EAAE;IACjC,MAAM,UAAU,GAAG,UAAU,EAAE,UAAU,IAAI,EAAE,CAAC;IAEhD,MAAM,aAAa,GAAG,UAAU,CAAC,IAAI,CACnC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,KAAK,cAAc,CAAC,wBAAwB,CAC1E,EAAE,KAAK,CAAC,IAAI,CAAC;IAEd,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAC9B,UAAU,CAAC,OAAO,CAAC,CAAC,SAAS,EAAE,EAAE;QAC/B,IAAI,SAAS,CAAC,IAAI,KAAK,cAAc,CAAC,eAAe,EAAE,CAAC;YACtD,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,YAAY,GAChB,SAAS,CAAC,QAAQ,CAAC,IAAI,KAAK,cAAc,CAAC,UAAU;YACnD,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI;YACzB,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC;QAE/B,OAAO,OAAO,YAAY,KAAK,QAAQ;YACrC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,EAAE,YAAY,CAAU,CAAC;YACjD,CAAC,CAAC,EAAE,CAAC;IACT,CAAC,CAAC,CACH,CAAC;IAEF,6EAA6E;IAC7E,uEAAuE;IACvE,yBAAyB;IACzB,MAAM,OAAO,GAAG,CACd,MAAyC,EACb,EAAE;QAC9B,IAAI,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC;YAC1B,OAAO,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QACpC,CAAC;QAED,IAAI,MAAM,CAAC,IAAI,KAAK,cAAc,CAAC,UAAU,EAAE,CAAC;YAC9C,MAAM,aAAa,GAAG,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAExD,OAAO,aAAa,KAAK,SAAS;gBAChC,CAAC,CAAC,SAAS;gBACX,CAAC,CAAC;oBACE,aAAa;oBACb,oEAAoE;oBACpE,YAAY,EAAE,MAAuB;oBACrC,WAAW,EAAE,KAAK;iBACnB,CAAC;QACR,CAAC;QAED,IACE,aAAa,KAAK,SAAS;YAC3B,MAAM,CAAC,IAAI,KAAK,cAAc,CAAC,gBAAgB;YAC/C,MAAM,CAAC,QAAQ;YACf,MAAM,CAAC,QAAQ,CAAC,IAAI,KAAK,cAAc,CAAC,UAAU,EAClD,CAAC;YACD,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,MAAM,MAAM,GAAG,wBAAwB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAEvD,OAAO,MAAM,CAAC,IAAI,KAAK,cAAc,CAAC,UAAU;YAC9C,MAAM,CAAC,IAAI,KAAK,aAAa;YAC7B,CAAC,CAAC;gBACE,aAAa,EAAE,MAAM,CAAC,QAAQ,CAAC,IAAI;gBACnC,oEAAoE;gBACpE,YAAY,EAAE,MAAM,CAAC,QAAyB;gBAC9C,WAAW,EAAE,IAAI;aAClB;YACH,CAAC,CAAC,SAAS,CAAC;IAChB,CAAC,CAAC;IAEF,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC;AAEF,MAAM,wBAAwB,GAAG,CAC/B,IAAuC,EACJ,EAAE,CACrC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,wBAAwB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAEzE,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAC9B,KAAyB,EACzB,OAAyB,EACzB,kBAA0D,EAC1D,aAAgC,EACH,EAAE;IAC/B,MAAM,aAAa,GAAG,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAE/C,MAAM,eAAe,GACnB,YAAY,aAAa,YAAY,oBAAoB,IAAa,CAAC;IAEzE,MAAM,OAAO,GAAG,IAAI,CAAC;IAErB,MAAM,aAAa,GAAG,GAAG,eAAe,GAAG,OAAO,EAAW,CAAC;IAE9D,6CAA6C;IAC7C,uDAAuD;IACvD,OAAO,CAAC,KAAK,CAAC,gBAAgB,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC;AAC1D,CAAC,CAAC"}
|
|
@@ -1,175 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
AST_NODE_TYPES,
|
|
3
|
-
type TSESLint,
|
|
4
|
-
type TSESTree,
|
|
5
|
-
} from '@typescript-eslint/utils';
|
|
6
|
-
import type { DeepReadonly } from 'ts-type-forge';
|
|
7
|
-
import { isTypeWrapper } from './ast-utils.mjs';
|
|
8
|
-
import { TS_DATA_FORGE_MODULE } from './constants.mjs';
|
|
9
|
-
|
|
10
|
-
/* eslint-disable @typescript-eslint/prefer-readonly-parameter-types */
|
|
11
|
-
|
|
12
|
-
export const getTsDataForgeImport = (
|
|
13
|
-
program: TSESTree.Program,
|
|
14
|
-
): TSESTree.ImportDeclaration | undefined =>
|
|
15
|
-
program.body.find(
|
|
16
|
-
(node): node is TSESTree.ImportDeclaration =>
|
|
17
|
-
node.type === AST_NODE_TYPES.ImportDeclaration &&
|
|
18
|
-
node.source.value === TS_DATA_FORGE_MODULE,
|
|
19
|
-
);
|
|
20
|
-
|
|
21
|
-
export const getNamedImports = (
|
|
22
|
-
node: DeepReadonly<TSESTree.ImportDeclaration> | undefined,
|
|
23
|
-
): readonly string[] => {
|
|
24
|
-
if (node === undefined) {
|
|
25
|
-
return [];
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
return node.specifiers.flatMap((specifier) =>
|
|
29
|
-
specifier.type === AST_NODE_TYPES.ImportSpecifier
|
|
30
|
-
? (() => {
|
|
31
|
-
const importedName =
|
|
32
|
-
specifier.imported.type === AST_NODE_TYPES.Identifier
|
|
33
|
-
? specifier.imported.name
|
|
34
|
-
: specifier.imported.value;
|
|
35
|
-
|
|
36
|
-
return typeof importedName === 'string' ? [importedName] : [];
|
|
37
|
-
})()
|
|
38
|
-
: [],
|
|
39
|
-
);
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Returns the in-scope local name a given canonical export is imported as
|
|
44
|
-
* (handling aliases such as `import { isX as y }` → `'y'`), or `undefined` when
|
|
45
|
-
* it is not imported. Used so autofixes reference the binding that actually
|
|
46
|
-
* exists rather than the canonical name.
|
|
47
|
-
*/
|
|
48
|
-
export const getImportedLocalName = (
|
|
49
|
-
node: DeepReadonly<TSESTree.ImportDeclaration> | undefined,
|
|
50
|
-
importedName: string,
|
|
51
|
-
): string | undefined =>
|
|
52
|
-
node?.specifiers.find(
|
|
53
|
-
(specifier) =>
|
|
54
|
-
specifier.type === AST_NODE_TYPES.ImportSpecifier &&
|
|
55
|
-
(specifier.imported.type === AST_NODE_TYPES.Identifier
|
|
56
|
-
? specifier.imported.name
|
|
57
|
-
: specifier.imported.value) === importedName,
|
|
58
|
-
)?.local.name;
|
|
59
|
-
|
|
60
|
-
type ResolvedCallee = Readonly<{
|
|
61
|
-
/** The canonical (imported) ts-data-forge name, regardless of local alias. */
|
|
62
|
-
canonicalName: string;
|
|
63
|
-
/** The identifier node to rewrite when replacing the callee name. */
|
|
64
|
-
propertyNode: TSESTree.Node;
|
|
65
|
-
/** Whether the call was made through a namespace import (`tf.isX(...)`). */
|
|
66
|
-
isNamespace: boolean;
|
|
67
|
-
}>;
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Builds a resolver that maps a call expression's callee to the canonical
|
|
71
|
-
* ts-data-forge function it refers to. Handles named imports (including aliases
|
|
72
|
-
* such as `import { isX as y }`) and namespace imports (`import * as tf` →
|
|
73
|
-
* `tf.isX(...)`). Returns `undefined` for any callee that does not reference the
|
|
74
|
-
* given ts-data-forge import.
|
|
75
|
-
*/
|
|
76
|
-
export const buildCalleeResolver = (
|
|
77
|
-
importDecl: TSESTree.ImportDeclaration | undefined,
|
|
78
|
-
): ((
|
|
79
|
-
callee: DeepReadonly<TSESTree.Expression>,
|
|
80
|
-
) => ResolvedCallee | undefined) => {
|
|
81
|
-
const specifiers = importDecl?.specifiers ?? [];
|
|
82
|
-
|
|
83
|
-
const namespaceName = specifiers.find(
|
|
84
|
-
(specifier) => specifier.type === AST_NODE_TYPES.ImportNamespaceSpecifier,
|
|
85
|
-
)?.local.name;
|
|
86
|
-
|
|
87
|
-
const localToCanonical = new Map<string, string>(
|
|
88
|
-
specifiers.flatMap((specifier) => {
|
|
89
|
-
if (specifier.type !== AST_NODE_TYPES.ImportSpecifier) {
|
|
90
|
-
return [];
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
const importedName =
|
|
94
|
-
specifier.imported.type === AST_NODE_TYPES.Identifier
|
|
95
|
-
? specifier.imported.name
|
|
96
|
-
: specifier.imported.value;
|
|
97
|
-
|
|
98
|
-
return typeof importedName === 'string'
|
|
99
|
-
? [[specifier.local.name, importedName] as const]
|
|
100
|
-
: [];
|
|
101
|
-
}),
|
|
102
|
-
);
|
|
103
|
-
|
|
104
|
-
// `(isNull as (u: unknown) => boolean)(x)` and `(tf as typeof tf).isNull(x)`
|
|
105
|
-
// still call `isNull`: both the callee and a namespace object are read
|
|
106
|
-
// through type wrappers.
|
|
107
|
-
const resolve = (
|
|
108
|
-
callee: DeepReadonly<TSESTree.Expression>,
|
|
109
|
-
): ResolvedCallee | undefined => {
|
|
110
|
-
if (isTypeWrapper(callee)) {
|
|
111
|
-
return resolve(callee.expression);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
if (callee.type === AST_NODE_TYPES.Identifier) {
|
|
115
|
-
const canonicalName = localToCanonical.get(callee.name);
|
|
116
|
-
|
|
117
|
-
return canonicalName === undefined
|
|
118
|
-
? undefined
|
|
119
|
-
: {
|
|
120
|
-
canonicalName,
|
|
121
|
-
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
122
|
-
propertyNode: callee as TSESTree.Node,
|
|
123
|
-
isNamespace: false,
|
|
124
|
-
};
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
if (
|
|
128
|
-
namespaceName === undefined ||
|
|
129
|
-
callee.type !== AST_NODE_TYPES.MemberExpression ||
|
|
130
|
-
callee.computed ||
|
|
131
|
-
callee.property.type !== AST_NODE_TYPES.Identifier
|
|
132
|
-
) {
|
|
133
|
-
return undefined;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
const object = skipReadonlyTypeWrappers(callee.object);
|
|
137
|
-
|
|
138
|
-
return object.type === AST_NODE_TYPES.Identifier &&
|
|
139
|
-
object.name === namespaceName
|
|
140
|
-
? {
|
|
141
|
-
canonicalName: callee.property.name,
|
|
142
|
-
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
143
|
-
propertyNode: callee.property as TSESTree.Node,
|
|
144
|
-
isNamespace: true,
|
|
145
|
-
}
|
|
146
|
-
: undefined;
|
|
147
|
-
};
|
|
148
|
-
|
|
149
|
-
return resolve;
|
|
150
|
-
};
|
|
151
|
-
|
|
152
|
-
const skipReadonlyTypeWrappers = (
|
|
153
|
-
node: DeepReadonly<TSESTree.Expression>,
|
|
154
|
-
): DeepReadonly<TSESTree.Expression> =>
|
|
155
|
-
isTypeWrapper(node) ? skipReadonlyTypeWrappers(node.expression) : node;
|
|
156
|
-
|
|
157
|
-
export const buildImportFixes = (
|
|
158
|
-
fixer: TSESLint.RuleFixer,
|
|
159
|
-
program: TSESTree.Program,
|
|
160
|
-
_tsDataForgeImport: TSESTree.ImportDeclaration | undefined,
|
|
161
|
-
requiredNames: readonly string[],
|
|
162
|
-
): readonly TSESLint.RuleFix[] => {
|
|
163
|
-
const specifierText = requiredNames.join(', ');
|
|
164
|
-
|
|
165
|
-
const importStatement =
|
|
166
|
-
`import { ${specifierText} } from '${TS_DATA_FORGE_MODULE}';` as const;
|
|
167
|
-
|
|
168
|
-
const newLine = '\n';
|
|
169
|
-
|
|
170
|
-
const insertionText = `${importStatement}${newLine}` as const;
|
|
171
|
-
|
|
172
|
-
// Always insert at the beginning of the file
|
|
173
|
-
// (organize-imports will handle merging/deduplication)
|
|
174
|
-
return [fixer.insertTextBefore(program, insertionText)];
|
|
175
|
-
};
|