eslint-plugin-ts-std-forge 0.1.7 → 0.1.8
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 -26
- package/dist/rules/ast-utils.d.mts.map +1 -1
- package/dist/rules/ast-utils.mjs +2 -65
- package/dist/rules/ast-utils.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 +7 -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 +6 -5
- package/dist/rules/prefer-is-record-and-has-key.mjs.map +1 -1
- package/dist/rules/prefer-safe-array-is-array.d.mts.map +1 -1
- package/dist/rules/prefer-safe-array-is-array.mjs +8 -5
- package/dist/rules/prefer-safe-array-is-array.mjs.map +1 -1
- package/dist/rules/prefer-safe-array-length-guard.d.mts.map +1 -1
- package/dist/rules/prefer-safe-array-length-guard.mjs +8 -5
- package/dist/rules/prefer-safe-array-length-guard.mjs.map +1 -1
- package/dist/rules/prefer-safe-number-parse-integer.d.mts.map +1 -1
- package/dist/rules/prefer-safe-number-parse-integer.mjs +6 -5
- package/dist/rules/prefer-safe-number-parse-integer.mjs.map +1 -1
- package/dist/rules/prefer-safe-number-parse.d.mts.map +1 -1
- package/dist/rules/prefer-safe-number-parse.mjs +6 -5
- package/dist/rules/prefer-safe-number-parse.mjs.map +1 -1
- package/package.json +5 -4
- package/src/rules/ast-utils.mts +1 -90
- package/src/rules/prefer-is-non-null-object.mts +13 -7
- package/src/rules/prefer-is-record-and-has-key.mts +19 -13
- package/src/rules/prefer-safe-array-is-array.mts +14 -10
- package/src/rules/prefer-safe-array-is-array.test.mts +14 -0
- package/src/rules/prefer-safe-array-length-guard.mts +15 -11
- package/src/rules/prefer-safe-number-parse-integer.mts +18 -12
- package/src/rules/prefer-safe-number-parse.mts +18 -12
- package/dist/rules/import-utils.d.mts +0 -6
- package/dist/rules/import-utils.d.mts.map +0 -1
- package/dist/rules/import-utils.mjs +0 -28
- package/dist/rules/import-utils.mjs.map +0 -1
- package/src/rules/import-utils.mts +0 -58
|
@@ -1,24 +1,10 @@
|
|
|
1
1
|
import { type TSESLint, type TSESTree } from '@typescript-eslint/utils';
|
|
2
2
|
import type * as ts from 'typescript';
|
|
3
|
-
/**
|
|
4
|
-
* `node` with every `as`, `satisfies`, `!` and `<T>` around it taken off: the
|
|
5
|
-
* expression whose value it is. Judge syntax and ask types on what this
|
|
6
|
-
* returns, so that a wrapper neither hides a pattern (`xs.length > (0 as
|
|
7
|
-
* const)`) nor vouches for a type (`Number(b as unknown as string)`, whose
|
|
8
|
-
* value is still a boolean), and keep the original node for fix text. See
|
|
9
|
-
* `docs/writing-lint-rules.md` at the repository root.
|
|
10
|
-
*
|
|
11
|
-
* A copy of the helper in `eslint-config-typed`, which this package, published
|
|
12
|
-
* on its own, cannot import.
|
|
13
|
-
*/
|
|
14
|
-
export declare const skipTypeWrappers: (node: TSESTree.Node) => TSESTree.Node;
|
|
15
|
-
export declare const isTypeWrapper: (node: TSESTree.Node) => node is TypeWrapper;
|
|
16
3
|
/**
|
|
17
4
|
* Whether `node`, read through its type wrappers, is the identifier `name`:
|
|
18
5
|
* `Number`, `(Number as NumberConstructor)` and `Number!` are the same object.
|
|
19
6
|
*/
|
|
20
7
|
export declare const isIdentifierNamed: (node: TSESTree.Node, name: string) => boolean;
|
|
21
|
-
export type TypeWrapper = TSESTree.TSAsExpression | TSESTree.TSNonNullExpression | TSESTree.TSSatisfiesExpression | TSESTree.TSTypeAssertion;
|
|
22
8
|
/**
|
|
23
9
|
* The type of the value `node` evaluates to, asked of the expression inside
|
|
24
10
|
* its type wrappers rather than of the cast, or `undefined` without type
|
|
@@ -26,16 +12,4 @@ export type TypeWrapper = TSESTree.TSAsExpression | TSESTree.TSNonNullExpression
|
|
|
26
12
|
* out, since that much the source asserts about the value itself.
|
|
27
13
|
*/
|
|
28
14
|
export declare const getValueType: (sourceCode: TSESLint.SourceCode, node: TSESTree.Node) => ts.Type | undefined;
|
|
29
|
-
/**
|
|
30
|
-
* The source text of `node` to put in a call's argument list. `getText`
|
|
31
|
-
* leaves out the parentheses the source puts around a node, and a sequence
|
|
32
|
-
* `(a, b)` without them would be read as two arguments.
|
|
33
|
-
*/
|
|
34
|
-
export declare const getArgumentText: (sourceCode: TSESLint.SourceCode, node: TSESTree.Node) => string;
|
|
35
|
-
/**
|
|
36
|
-
* The range of `node` together with the parentheses the source puts around it,
|
|
37
|
-
* which `node.range` leaves out: all of `((Array.isArray))` for the member
|
|
38
|
-
* expression inside.
|
|
39
|
-
*/
|
|
40
|
-
export declare const getRangeWithParens: (sourceCode: TSESLint.SourceCode, node: TSESTree.Node) => TSESTree.Range;
|
|
41
15
|
//# sourceMappingURL=ast-utils.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ast-utils.d.mts","sourceRoot":"","sources":["../../src/rules/ast-utils.mts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"ast-utils.d.mts","sourceRoot":"","sources":["../../src/rules/ast-utils.mts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,QAAQ,EACb,KAAK,QAAQ,EACd,MAAM,0BAA0B,CAAC;AAElC,OAAO,KAAK,KAAK,EAAE,MAAM,YAAY,CAAC;AAEtC;;;GAGG;AACH,eAAO,MAAM,iBAAiB,SAEtB,QAAQ,CAAC,IAAI,QACb,MAAM,KACX,OAMF,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,YAAY,eAEX,QAAQ,CAAC,UAAU,QAEzB,QAAQ,CAAC,IAAI,KAClB,EAAE,CAAC,IAAI,GAAG,SAcZ,CAAC"}
|
package/dist/rules/ast-utils.mjs
CHANGED
|
@@ -1,21 +1,5 @@
|
|
|
1
|
-
import { AST_NODE_TYPES,
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
export const skipTypeWrappers = (
|
|
14
|
-
|
|
15
|
-
node) => isTypeWrapper(node) ? skipTypeWrappers(node.expression) : node;
|
|
16
|
-
export const isTypeWrapper = (
|
|
17
|
-
|
|
18
|
-
node) => TYPE_WRAPPERS.has(node.type);
|
|
1
|
+
import { AST_NODE_TYPES, } from '@typescript-eslint/utils';
|
|
2
|
+
import { isTypeWrapper, skipTypeWrappers } from 'eslint-rule-forge';
|
|
19
3
|
|
|
20
4
|
|
|
21
5
|
|
|
@@ -46,56 +30,9 @@ node) => {
|
|
|
46
30
|
const type = checker.getTypeAtLocation(tsNode);
|
|
47
31
|
return hasNonNullAssertion(node) ? checker.getNonNullableType(type) : type;
|
|
48
32
|
};
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
export const getArgumentText = (
|
|
55
|
-
|
|
56
|
-
sourceCode,
|
|
57
|
-
|
|
58
|
-
node) => {
|
|
59
|
-
const text = sourceCode.getText(node);
|
|
60
|
-
return node.type === AST_NODE_TYPES.SequenceExpression ? `(${text})` : text;
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
export const getRangeWithParens = (
|
|
68
|
-
|
|
69
|
-
sourceCode,
|
|
70
|
-
|
|
71
|
-
node) => {
|
|
72
|
-
const depth = parenthesesDepth(sourceCode, node);
|
|
73
|
-
if (depth === 0) {
|
|
74
|
-
return node.range;
|
|
75
|
-
}
|
|
76
|
-
const opening = sourceCode.getTokenBefore(node, { skip: depth - 1 });
|
|
77
|
-
const closing = sourceCode.getTokenAfter(node, { skip: depth - 1 });
|
|
78
|
-
return opening === null || closing === null
|
|
79
|
-
? node.range
|
|
80
|
-
: [opening.range[0], closing.range[1]];
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
const parenthesesDepth = (
|
|
84
|
-
|
|
85
|
-
sourceCode,
|
|
86
|
-
|
|
87
|
-
node, depth = 0) => ASTUtils.isParenthesized(depth + 1, node, sourceCode)
|
|
88
|
-
? parenthesesDepth(sourceCode, node, depth + 1)
|
|
89
|
-
: depth;
|
|
90
33
|
const hasNonNullAssertion = (
|
|
91
34
|
|
|
92
35
|
node) => isTypeWrapper(node) &&
|
|
93
36
|
(node.type === AST_NODE_TYPES.TSNonNullExpression ||
|
|
94
37
|
hasNonNullAssertion(node.expression));
|
|
95
|
-
const TYPE_WRAPPERS = new Set([
|
|
96
|
-
AST_NODE_TYPES.TSAsExpression,
|
|
97
|
-
AST_NODE_TYPES.TSNonNullExpression,
|
|
98
|
-
AST_NODE_TYPES.TSSatisfiesExpression,
|
|
99
|
-
AST_NODE_TYPES.TSTypeAssertion,
|
|
100
|
-
]);
|
|
101
38
|
//# sourceMappingURL=ast-utils.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ast-utils.mjs","sourceRoot":"","sources":["../../src/rules/ast-utils.mts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,
|
|
1
|
+
{"version":3,"file":"ast-utils.mjs","sourceRoot":"","sources":["../../src/rules/ast-utils.mts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,GAGf,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAGpE;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG;AAC/B,8EAA8E;AAC9E,IAAmB,EACnB,IAAY,EACH,EAAE;IACX,MAAM,SAAS,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;IAEzC,OAAO,CACL,SAAS,CAAC,IAAI,KAAK,cAAc,CAAC,UAAU,IAAI,SAAS,CAAC,IAAI,KAAK,IAAI,CACxE,CAAC;AACJ,CAAC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG;AAC1B,8EAA8E;AAC9E,UAA+B;AAC/B,8EAA8E;AAC9E,IAAmB,EACE,EAAE;IACvB,MAAM,QAAQ,GAAG,UAAU,CAAC,cAAc,CAAC;IAE3C,MAAM,OAAO,GAAG,QAAQ,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC;IAEpD,MAAM,MAAM,GAAG,QAAQ,EAAE,qBAAqB,EAAE,GAAG,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC;IAE5E,IAAI,OAAO,KAAK,SAAS,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QAClD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,IAAI,GAAG,OAAO,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAE/C,OAAO,mBAAmB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAC7E,CAAC,CAAC;AAEF,MAAM,mBAAmB,GAAG;AAC1B,8EAA8E;AAC9E,IAAmB,EACV,EAAE,CACX,aAAa,CAAC,IAAI,CAAC;IACnB,CAAC,IAAI,CAAC,IAAI,KAAK,cAAc,CAAC,mBAAmB;QAC/C,mBAAmB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prefer-is-non-null-object.d.mts","sourceRoot":"","sources":["../../src/rules/prefer-is-non-null-object.mts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,QAAQ,EAEd,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"prefer-is-non-null-object.d.mts","sourceRoot":"","sources":["../../src/rules/prefer-is-non-null-object.mts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,QAAQ,EAEd,MAAM,0BAA0B,CAAC;AASlC,KAAK,OAAO,GAAG,SAAS,EAAE,CAAC;AAE3B,KAAK,UAAU,GAAG,oBAAoB,CAAC;AAEvC,eAAO,MAAM,qBAAqB,EAAE,QAAQ,CAAC,UAAU,CAAC,UAAU,EAAE,OAAO,CA0EjE,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AST_NODE_TYPES, } from '@typescript-eslint/utils';
|
|
2
|
-
import { skipTypeWrappers } from '
|
|
3
|
-
import {
|
|
2
|
+
import { buildNamedImportFix, getImportDeclarations, getNamedImports, skipTypeWrappers, } from 'eslint-rule-forge';
|
|
3
|
+
import { TS_STD_FORGE_MODULE } from './constants.mjs';
|
|
4
4
|
export const preferIsNonNullObject = {
|
|
5
5
|
meta: {
|
|
6
6
|
type: 'suggestion',
|
|
@@ -16,7 +16,7 @@ export const preferIsNonNullObject = {
|
|
|
16
16
|
create: (context) => {
|
|
17
17
|
const sourceCode = context.sourceCode;
|
|
18
18
|
const program = sourceCode.ast;
|
|
19
|
-
const
|
|
19
|
+
const tsStdForgeImports = getImportDeclarations(program, TS_STD_FORGE_MODULE);
|
|
20
20
|
const mut_nodesToFix = [];
|
|
21
21
|
return {
|
|
22
22
|
LogicalExpression: (node) => {
|
|
@@ -27,7 +27,7 @@ export const preferIsNonNullObject = {
|
|
|
27
27
|
mut_nodesToFix.push({ node, identifierName });
|
|
28
28
|
},
|
|
29
29
|
'Program:exit': () => {
|
|
30
|
-
const hasIsNonNullObjectImport = getNamedImports(
|
|
30
|
+
const hasIsNonNullObjectImport = getNamedImports(tsStdForgeImports).includes('isNonNullObject');
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
|
|
@@ -40,7 +40,9 @@ export const preferIsNonNullObject = {
|
|
|
40
40
|
fix: (fixer) => {
|
|
41
41
|
const replacement = `isNonNullObject(${identifierName})`;
|
|
42
42
|
const importFixes = index === 0 && !hasIsNonNullObjectImport
|
|
43
|
-
?
|
|
43
|
+
? buildNamedImportFix(fixer, program, TS_STD_FORGE_MODULE, [
|
|
44
|
+
'isNonNullObject',
|
|
45
|
+
])
|
|
44
46
|
: [];
|
|
45
47
|
return [...importFixes, fixer.replaceText(node, replacement)];
|
|
46
48
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prefer-is-non-null-object.mjs","sourceRoot":"","sources":["../../src/rules/prefer-is-non-null-object.mts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,GAGf,MAAM,0BAA0B,CAAC;AAClC,OAAO,
|
|
1
|
+
{"version":3,"file":"prefer-is-non-null-object.mjs","sourceRoot":"","sources":["../../src/rules/prefer-is-non-null-object.mts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prefer-is-record-and-has-key.d.mts","sourceRoot":"","sources":["../../src/rules/prefer-is-record-and-has-key.mts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,QAAQ,EAEd,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"prefer-is-record-and-has-key.d.mts","sourceRoot":"","sources":["../../src/rules/prefer-is-record-and-has-key.mts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,QAAQ,EAEd,MAAM,0BAA0B,CAAC;AAalC,KAAK,OAAO,GAAG,SAAS,EAAE,CAAC;AAE3B,KAAK,UAAU,GAAG,sBAAsB,GAAG,WAAW,CAAC;AAEvD,eAAO,MAAM,uBAAuB,EAAE,QAAQ,CAAC,UAAU,CAAC,UAAU,EAAE,OAAO,CAsLjE,CAAC"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { AST_NODE_TYPES, } from '@typescript-eslint/utils';
|
|
2
|
+
import { buildNamedImportFix, getArgumentText, getImportDeclarations, getNamedImports, skipTypeWrappers, } from 'eslint-rule-forge';
|
|
2
3
|
import { SafeArray } from 'ts-std-forge';
|
|
3
4
|
import * as ts from 'typescript';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
5
|
+
import { getValueType, isIdentifierNamed } from './ast-utils.mjs';
|
|
6
|
+
import { TS_STD_FORGE_MODULE } from './constants.mjs';
|
|
6
7
|
export const preferIsRecordAndHasKey = {
|
|
7
8
|
meta: {
|
|
8
9
|
type: 'suggestion',
|
|
@@ -19,7 +20,7 @@ export const preferIsRecordAndHasKey = {
|
|
|
19
20
|
create: (context) => {
|
|
20
21
|
const sourceCode = context.sourceCode;
|
|
21
22
|
const program = sourceCode.ast;
|
|
22
|
-
const
|
|
23
|
+
const tsStdForgeImports = getImportDeclarations(program, TS_STD_FORGE_MODULE);
|
|
23
24
|
const checker = sourceCode.parserServices?.program?.getTypeChecker();
|
|
24
25
|
|
|
25
26
|
|
|
@@ -86,7 +87,7 @@ export const preferIsRecordAndHasKey = {
|
|
|
86
87
|
});
|
|
87
88
|
},
|
|
88
89
|
'Program:exit': () => {
|
|
89
|
-
const namedImports = getNamedImports(
|
|
90
|
+
const namedImports = getNamedImports(tsStdForgeImports);
|
|
90
91
|
const rewrites = mut_nodesToFix.map((entry) => ({
|
|
91
92
|
...entry,
|
|
92
93
|
|
|
@@ -120,7 +121,7 @@ export const preferIsRecordAndHasKey = {
|
|
|
120
121
|
|
|
121
122
|
|
|
122
123
|
const importFixes = index === 0 && importsToAdd.length > 0
|
|
123
|
-
?
|
|
124
|
+
? buildNamedImportFix(fixer, program, TS_STD_FORGE_MODULE, importsToAdd)
|
|
124
125
|
: [];
|
|
125
126
|
return [...importFixes, fixer.replaceText(node, replacement)];
|
|
126
127
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prefer-is-record-and-has-key.mjs","sourceRoot":"","sources":["../../src/rules/prefer-is-record-and-has-key.mts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,GAGf,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AACjC,OAAO,
|
|
1
|
+
{"version":3,"file":"prefer-is-record-and-has-key.mjs","sourceRoot":"","sources":["../../src/rules/prefer-is-record-and-has-key.mts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prefer-safe-array-is-array.d.mts","sourceRoot":"","sources":["../../src/rules/prefer-safe-array-is-array.mts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,QAAQ,EAEd,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"prefer-safe-array-is-array.d.mts","sourceRoot":"","sources":["../../src/rules/prefer-safe-array-is-array.mts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,QAAQ,EAEd,MAAM,0BAA0B,CAAC;AAWlC,KAAK,OAAO,GAAG,SAAS,EAAE,CAAC;AAE3B,KAAK,UAAU,GAAG,qBAAqB,CAAC;AAExC,eAAO,MAAM,sBAAsB,EAAE,QAAQ,CAAC,UAAU,CAAC,UAAU,EAAE,OAAO,CA0EhE,CAAC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { AST_NODE_TYPES, } from '@typescript-eslint/utils';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { buildNamedImportFix, getImportDeclarations, getNamedImports, getRangeWithParens, skipTypeWrappers, } from 'eslint-rule-forge';
|
|
3
|
+
import { isIdentifierNamed } from './ast-utils.mjs';
|
|
4
|
+
import { TS_STD_FORGE_MODULE } from './constants.mjs';
|
|
4
5
|
export const preferSafeArrayIsArray = {
|
|
5
6
|
meta: {
|
|
6
7
|
type: 'suggestion',
|
|
@@ -16,7 +17,7 @@ export const preferSafeArrayIsArray = {
|
|
|
16
17
|
create: (context) => {
|
|
17
18
|
const sourceCode = context.sourceCode;
|
|
18
19
|
const program = sourceCode.ast;
|
|
19
|
-
const
|
|
20
|
+
const tsStdForgeImports = getImportDeclarations(program, TS_STD_FORGE_MODULE);
|
|
20
21
|
const mut_nodesToFix = [];
|
|
21
22
|
return {
|
|
22
23
|
CallExpression: (node) => {
|
|
@@ -26,7 +27,7 @@ export const preferSafeArrayIsArray = {
|
|
|
26
27
|
mut_nodesToFix.push(node);
|
|
27
28
|
},
|
|
28
29
|
'Program:exit': () => {
|
|
29
|
-
const hasSafeArrayImport = getNamedImports(
|
|
30
|
+
const hasSafeArrayImport = getNamedImports(tsStdForgeImports).includes('SafeArray');
|
|
30
31
|
|
|
31
32
|
|
|
32
33
|
|
|
@@ -38,7 +39,9 @@ export const preferSafeArrayIsArray = {
|
|
|
38
39
|
messageId: 'useSafeArrayIsArray',
|
|
39
40
|
fix: (fixer) => {
|
|
40
41
|
const importFixes = index === 0 && !hasSafeArrayImport
|
|
41
|
-
?
|
|
42
|
+
? buildNamedImportFix(fixer, program, TS_STD_FORGE_MODULE, [
|
|
43
|
+
'SafeArray',
|
|
44
|
+
])
|
|
42
45
|
: [];
|
|
43
46
|
|
|
44
47
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prefer-safe-array-is-array.mjs","sourceRoot":"","sources":["../../src/rules/prefer-safe-array-is-array.mts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,GAGf,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,kBAAkB,EAClB,
|
|
1
|
+
{"version":3,"file":"prefer-safe-array-is-array.mjs","sourceRoot":"","sources":["../../src/rules/prefer-safe-array-is-array.mts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prefer-safe-array-length-guard.d.mts","sourceRoot":"","sources":["../../src/rules/prefer-safe-array-length-guard.mts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,QAAQ,EAEd,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"prefer-safe-array-length-guard.d.mts","sourceRoot":"","sources":["../../src/rules/prefer-safe-array-length-guard.mts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,QAAQ,EAEd,MAAM,0BAA0B,CAAC;AAYlC,KAAK,OAAO,GAAG,SAAS,EAAE,CAAC;AAE3B,KAAK,UAAU,GAAG,YAAY,GAAG,eAAe,CAAC;AAwCjD,eAAO,MAAM,0BAA0B,EAAE,QAAQ,CAAC,UAAU,CAC1D,UAAU,EACV,OAAO,CAgHC,CAAC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { AST_NODE_TYPES, } from '@typescript-eslint/utils';
|
|
2
|
-
import { getArgumentText,
|
|
3
|
-
import {
|
|
2
|
+
import { buildNamedImportFix, getArgumentText, getImportDeclarations, getNamedImports, skipTypeWrappers, } from 'eslint-rule-forge';
|
|
3
|
+
import { getValueType } from './ast-utils.mjs';
|
|
4
|
+
import { TS_STD_FORGE_MODULE } from './constants.mjs';
|
|
4
5
|
|
|
5
6
|
|
|
6
7
|
|
|
@@ -46,7 +47,7 @@ export const preferSafeArrayLengthGuard = {
|
|
|
46
47
|
create: (context) => {
|
|
47
48
|
const sourceCode = context.sourceCode;
|
|
48
49
|
const program = sourceCode.ast;
|
|
49
|
-
const
|
|
50
|
+
const tsStdForgeImports = getImportDeclarations(program, TS_STD_FORGE_MODULE);
|
|
50
51
|
const checker = sourceCode.parserServices?.program?.getTypeChecker();
|
|
51
52
|
|
|
52
53
|
|
|
@@ -77,7 +78,7 @@ export const preferSafeArrayLengthGuard = {
|
|
|
77
78
|
mut_nodesToFix.push({ node, ...matched });
|
|
78
79
|
},
|
|
79
80
|
'Program:exit': () => {
|
|
80
|
-
const hasSafeArrayImport = getNamedImports(
|
|
81
|
+
const hasSafeArrayImport = getNamedImports(tsStdForgeImports).includes('SafeArray');
|
|
81
82
|
|
|
82
83
|
|
|
83
84
|
|
|
@@ -95,7 +96,9 @@ export const preferSafeArrayLengthGuard = {
|
|
|
95
96
|
fix: (fixer) => {
|
|
96
97
|
const replacement = `SafeArray.${guard}(${arrayText})`;
|
|
97
98
|
const importFixes = index === 0 && !hasSafeArrayImport
|
|
98
|
-
?
|
|
99
|
+
? buildNamedImportFix(fixer, program, TS_STD_FORGE_MODULE, [
|
|
100
|
+
'SafeArray',
|
|
101
|
+
])
|
|
99
102
|
: [];
|
|
100
103
|
return [...importFixes, fixer.replaceText(node, replacement)];
|
|
101
104
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prefer-safe-array-length-guard.mjs","sourceRoot":"","sources":["../../src/rules/prefer-safe-array-length-guard.mts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,GAGf,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"prefer-safe-array-length-guard.mjs","sourceRoot":"","sources":["../../src/rules/prefer-safe-array-length-guard.mts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,GAGf,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,mBAAmB,EACnB,eAAe,EACf,qBAAqB,EACrB,eAAe,EACf,gBAAgB,GACjB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAQtD;;;;;;;;;GASG;AACH,MAAM,WAAW,GAAG;IAClB,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE;IAC/C,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE;IAClD,EAAE,QAAQ,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE;IAChD,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE;CAK/C,CAAC;AAEL,wEAAwE;AACxE,MAAM,OAAO,GAAmC;IAC9C,KAAK,EAAE,KAAK;IACZ,KAAK,EAAE,KAAK;IACZ,GAAG,EAAE,GAAG;IACR,GAAG,EAAE,GAAG;IACR,IAAI,EAAE,IAAI;IACV,IAAI,EAAE,IAAI;CACF,CAAC;AAEX,MAAM,WAAW,GAAsC;IACrD,OAAO,EAAE,YAAY;IACrB,UAAU,EAAE,eAAe;CACnB,CAAC;AAEX,MAAM,CAAC,MAAM,0BAA0B,GAGnC;IACF,IAAI,EAAE;QACJ,IAAI,EAAE,YAAY;QAClB,IAAI,EAAE;YACJ,WAAW,EACT,+LAA+L;SAClM;QACD,OAAO,EAAE,MAAM;QACf,MAAM,EAAE,EAAE;QACV,QAAQ,EAAE;YACR,UAAU,EACR,uJAAuJ;YACzJ,aAAa,EACX,iKAAiK;SACpK;KACF;IAED,MAAM,EAAE,CAAC,OAAO,EAAE,EAAE;QAClB,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;QAEtC,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,CAAC;QAE/B,MAAM,iBAAiB,GAAG,qBAAqB,CAC7C,OAAO,EACP,mBAAmB,CACpB,CAAC;QAEF,MAAM,OAAO,GAAG,UAAU,CAAC,cAAc,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC;QAErE;;;;;WAKG;QACH,MAAM,WAAW,GAAG;QAClB,8EAA8E;QAC9E,UAA+B,EACtB,EAAE;YACX,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;gBAC1B,OAAO,KAAK,CAAC;YACf,CAAC;YAED,MAAM,IAAI,GAAG,YAAY,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;YAElD,OAAO,CACL,IAAI,KAAK,SAAS;gBAClB,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CACzD,CAAC;QACJ,CAAC,CAAC;QAEF,MAAM,cAAc,GAId,EAAE,CAAC;QAET,OAAO;YACL,gBAAgB,EAAE,CAAC,IAAI,EAAE,EAAE;gBACzB,MAAM,OAAO,GAAG,qBAAqB,CAAC,IAAI,CAAC,CAAC;gBAE5C,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;oBAC1B,OAAO;gBACT,CAAC;gBAED,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,eAAe,CAAC,EAAE,CAAC;oBAC1C,OAAO;gBACT,CAAC;gBAED,cAAc,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;YAC5C,CAAC;YACD,cAAc,EAAE,GAAG,EAAE;gBACnB,MAAM,kBAAkB,GACtB,eAAe,CAAC,iBAAiB,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;gBAE3D,iDAAiD;gBACjD,6DAA6D;gBAC7D,sEAAsE;gBACtE,qEAAqE;gBACrE,WAAW;gBACX,KAAK,MAAM,CACT,KAAK,EACL,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,EACjC,IAAI,cAAc,CAAC,OAAO,EAAE,EAAE,CAAC;oBAC9B,MAAM,SAAS,GAAG,eAAe,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC;oBAE/D,OAAO,CAAC,MAAM,CAAC;wBACb,IAAI;wBACJ,SAAS,EAAE,WAAW,CAAC,KAAK,CAAC;wBAC7B,IAAI,EAAE;4BACJ,QAAQ,EAAE,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC;4BAClC,SAAS,EAAE,SAAS;yBACrB;wBACD,GAAG,EAAE,CAAC,KAAK,EAAE,EAAE;4BACb,MAAM,WAAW,GAAG,aAAa,KAAK,IAAI,SAAS,GAAG,CAAC;4BAEvD,MAAM,WAAW,GACf,KAAK,KAAK,CAAC,IAAI,CAAC,kBAAkB;gCAChC,CAAC,CAAC,mBAAmB,CAAC,KAAK,EAAE,OAAO,EAAE,mBAAmB,EAAE;oCACvD,WAAW;iCACZ,CAAC;gCACJ,CAAC,CAAC,EAAE,CAAC;4BAET,OAAO,CAAC,GAAG,WAAW,EAAE,KAAK,CAAC,WAAW,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC;wBAChE,CAAC;qBACF,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;SACF,CAAC;IACJ,CAAC;IACD,cAAc,EAAE,EAAE;CACV,CAAC;AAEX;;;;GAIG;AACH,MAAM,qBAAqB,GAAG;AAC5B,6EAA6E;AAC7E,kEAAkE;AAClE,8EAA8E;AAC9E,IAA+B,EAGnB,EAAE;IACd,2EAA2E;IAC3E,oEAAoE;IACpE,MAAM,IAAI,GAAG,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEzC,MAAM,KAAK,GAAG,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAE3C,MAAM,YAAY,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;IAE1C,MAAM,UAAU,GAAG,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC;IAE/C,MAAM,SAAS,GAAG,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;IAE9C,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC,EAAE,CAAC;QAChC,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,uEAAuE;IACvE,8CAA8C;IAC9C,IACE,SAAS,CAAC,IAAI,KAAK,cAAc,CAAC,OAAO;QACzC,OAAO,SAAS,CAAC,KAAK,KAAK,QAAQ,EACnC,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,QAAQ,GAAG,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAEvE,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,CAC9B,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,KAAK,QAAQ,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS,CAAC,KAAK,CAC1E,CAAC;IAEF,OAAO,OAAO,KAAK,SAAS;QAC1B,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,EAAE,eAAe,EAAE,UAAU,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC;AACnE,CAAC,CAAC;AAEF,MAAM,cAAc,GAAG;AACrB,8EAA8E;AAC9E,IAAmB,EACgB,EAAE,CACrC,IAAI,CAAC,IAAI,KAAK,cAAc,CAAC,gBAAgB;IAC7C,CAAC,IAAI,CAAC,QAAQ;IACd,IAAI,CAAC,QAAQ,CAAC,IAAI,KAAK,cAAc,CAAC,UAAU;IAChD,IAAI,CAAC,QAAQ,CAAC,IAAI,KAAK,QAAQ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prefer-safe-number-parse-integer.d.mts","sourceRoot":"","sources":["../../src/rules/prefer-safe-number-parse-integer.mts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,QAAQ,EAEd,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"prefer-safe-number-parse-integer.d.mts","sourceRoot":"","sources":["../../src/rules/prefer-safe-number-parse-integer.mts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,QAAQ,EAEd,MAAM,0BAA0B,CAAC;AAYlC,KAAK,OAAO,GAAG,SAAS,EAAE,CAAC;AAE3B,KAAK,UAAU,GAAG,2BAA2B,CAAC;AAkB9C;;;;;;GAMG;AACH,eAAO,MAAM,4BAA4B,EAAE,QAAQ,CAAC,UAAU,CAC5D,UAAU,EACV,OAAO,CAgIC,CAAC"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { AST_NODE_TYPES, } from '@typescript-eslint/utils';
|
|
2
|
+
import { buildNamedImportFix, getArgumentText, getImportDeclarations, getNamedImports, skipTypeWrappers, } from 'eslint-rule-forge';
|
|
2
3
|
import * as ts from 'typescript';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
4
|
+
import { getValueType, isIdentifierNamed } from './ast-utils.mjs';
|
|
5
|
+
import { TS_STD_FORGE_MODULE } from './constants.mjs';
|
|
5
6
|
|
|
6
7
|
|
|
7
8
|
|
|
@@ -36,7 +37,7 @@ export const preferSafeNumberParseInteger = {
|
|
|
36
37
|
create: (context) => {
|
|
37
38
|
const sourceCode = context.sourceCode;
|
|
38
39
|
const program = sourceCode.ast;
|
|
39
|
-
const
|
|
40
|
+
const tsStdForgeImports = getImportDeclarations(program, TS_STD_FORGE_MODULE);
|
|
40
41
|
const mut_nodesToFix = [];
|
|
41
42
|
return {
|
|
42
43
|
CallExpression: (node) => {
|
|
@@ -80,7 +81,7 @@ export const preferSafeNumberParseInteger = {
|
|
|
80
81
|
mut_nodesToFix.push({ node, argExpression: firstArg });
|
|
81
82
|
},
|
|
82
83
|
'Program:exit': () => {
|
|
83
|
-
const namedImports = getNamedImports(
|
|
84
|
+
const namedImports = getNamedImports(tsStdForgeImports);
|
|
84
85
|
const missingImports = ['Result', 'SafeNumber'].filter((name) => !namedImports.includes(name));
|
|
85
86
|
for (const [index, { node, argExpression },] of mut_nodesToFix.entries()) {
|
|
86
87
|
const argText = getArgumentText(sourceCode, argExpression);
|
|
@@ -94,7 +95,7 @@ export const preferSafeNumberParseInteger = {
|
|
|
94
95
|
fix: (fixer) => {
|
|
95
96
|
const core = `Result.unwrapOkOr(SafeNumber.parseInteger(${argText}), Number.NaN)`;
|
|
96
97
|
const importFixes = index === 0 && missingImports.length > 0
|
|
97
|
-
?
|
|
98
|
+
? buildNamedImportFix(fixer, program, TS_STD_FORGE_MODULE, missingImports)
|
|
98
99
|
: [];
|
|
99
100
|
return [...importFixes, fixer.replaceText(node, core)];
|
|
100
101
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prefer-safe-number-parse-integer.mjs","sourceRoot":"","sources":["../../src/rules/prefer-safe-number-parse-integer.mts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,GAGf,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AACjC,OAAO,
|
|
1
|
+
{"version":3,"file":"prefer-safe-number-parse-integer.mjs","sourceRoot":"","sources":["../../src/rules/prefer-safe-number-parse-integer.mts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prefer-safe-number-parse.d.mts","sourceRoot":"","sources":["../../src/rules/prefer-safe-number-parse.mts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,QAAQ,EAEd,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"prefer-safe-number-parse.d.mts","sourceRoot":"","sources":["../../src/rules/prefer-safe-number-parse.mts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,QAAQ,EAEd,MAAM,0BAA0B,CAAC;AAYlC,KAAK,OAAO,GAAG,SAAS,EAAE,CAAC;AAE3B,KAAK,UAAU,GAAG,oBAAoB,CAAC;AAkBvC;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,qBAAqB,EAAE,QAAQ,CAAC,UAAU,CAAC,UAAU,EAAE,OAAO,CAyHjE,CAAC"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { AST_NODE_TYPES, } from '@typescript-eslint/utils';
|
|
2
|
+
import { buildNamedImportFix, getArgumentText, getImportDeclarations, getNamedImports, skipTypeWrappers, } from 'eslint-rule-forge';
|
|
2
3
|
import * as ts from 'typescript';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
4
|
+
import { getValueType, isIdentifierNamed } from './ast-utils.mjs';
|
|
5
|
+
import { TS_STD_FORGE_MODULE } from './constants.mjs';
|
|
5
6
|
|
|
6
7
|
|
|
7
8
|
|
|
@@ -42,7 +43,7 @@ export const preferSafeNumberParse = {
|
|
|
42
43
|
create: (context) => {
|
|
43
44
|
const sourceCode = context.sourceCode;
|
|
44
45
|
const program = sourceCode.ast;
|
|
45
|
-
const
|
|
46
|
+
const tsStdForgeImports = getImportDeclarations(program, TS_STD_FORGE_MODULE);
|
|
46
47
|
const mut_nodesToFix = [];
|
|
47
48
|
return {
|
|
48
49
|
CallExpression: (node) => {
|
|
@@ -81,7 +82,7 @@ export const preferSafeNumberParse = {
|
|
|
81
82
|
mut_nodesToFix.push({ node, argExpression: firstArg });
|
|
82
83
|
},
|
|
83
84
|
'Program:exit': () => {
|
|
84
|
-
const namedImports = getNamedImports(
|
|
85
|
+
const namedImports = getNamedImports(tsStdForgeImports);
|
|
85
86
|
const missingImports = ['Result', 'SafeNumber'].filter((name) => !namedImports.includes(name));
|
|
86
87
|
for (const [index, { node, argExpression },] of mut_nodesToFix.entries()) {
|
|
87
88
|
const argText = getArgumentText(sourceCode, argExpression);
|
|
@@ -95,7 +96,7 @@ export const preferSafeNumberParse = {
|
|
|
95
96
|
fix: (fixer) => {
|
|
96
97
|
const core = `Result.unwrapOkOr(SafeNumber.parse(${argText}), Number.NaN)`;
|
|
97
98
|
const importFixes = index === 0 && missingImports.length > 0
|
|
98
|
-
?
|
|
99
|
+
? buildNamedImportFix(fixer, program, TS_STD_FORGE_MODULE, missingImports)
|
|
99
100
|
: [];
|
|
100
101
|
return [...importFixes, fixer.replaceText(node, core)];
|
|
101
102
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prefer-safe-number-parse.mjs","sourceRoot":"","sources":["../../src/rules/prefer-safe-number-parse.mts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,GAGf,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AACjC,OAAO,
|
|
1
|
+
{"version":3,"file":"prefer-safe-number-parse.mjs","sourceRoot":"","sources":["../../src/rules/prefer-safe-number-parse.mts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-ts-std-forge",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.8",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "ESLint rules that steer code toward ts-std-forge idioms.",
|
|
6
6
|
"keywords": [
|
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
],
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"@typescript-eslint/utils": "^8.71.1",
|
|
38
|
+
"eslint-rule-forge": "^0.1.0",
|
|
38
39
|
"ts-std-forge": "0.5.1",
|
|
39
40
|
"ts-type-forge": "~9.2.2"
|
|
40
41
|
},
|
|
@@ -42,9 +43,9 @@
|
|
|
42
43
|
"@typescript-eslint/parser": "8.71.1",
|
|
43
44
|
"@typescript-eslint/rule-tester": "8.71.1",
|
|
44
45
|
"dedent": "1.7.2",
|
|
45
|
-
"eslint-config-typed": "5.17.
|
|
46
|
-
"eslint-plugin-ts-fortress": "1.3.
|
|
47
|
-
"eslint-plugin-ts-type-forge": "0.8.
|
|
46
|
+
"eslint-config-typed": "5.17.4",
|
|
47
|
+
"eslint-plugin-ts-fortress": "1.3.3",
|
|
48
|
+
"eslint-plugin-ts-type-forge": "0.8.8",
|
|
48
49
|
"prettier": "3.9.9",
|
|
49
50
|
"prettier-plugin-organize-imports": "4.3.0",
|
|
50
51
|
"prettier-plugin-packagejson": "3.0.2",
|
package/src/rules/ast-utils.mts
CHANGED
|
@@ -1,33 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AST_NODE_TYPES,
|
|
3
|
-
ASTUtils,
|
|
4
3
|
type TSESLint,
|
|
5
4
|
type TSESTree,
|
|
6
5
|
} from '@typescript-eslint/utils';
|
|
6
|
+
import { isTypeWrapper, skipTypeWrappers } from 'eslint-rule-forge';
|
|
7
7
|
import type * as ts from 'typescript';
|
|
8
8
|
|
|
9
|
-
/**
|
|
10
|
-
* `node` with every `as`, `satisfies`, `!` and `<T>` around it taken off: the
|
|
11
|
-
* expression whose value it is. Judge syntax and ask types on what this
|
|
12
|
-
* returns, so that a wrapper neither hides a pattern (`xs.length > (0 as
|
|
13
|
-
* const)`) nor vouches for a type (`Number(b as unknown as string)`, whose
|
|
14
|
-
* value is still a boolean), and keep the original node for fix text. See
|
|
15
|
-
* `docs/writing-lint-rules.md` at the repository root.
|
|
16
|
-
*
|
|
17
|
-
* A copy of the helper in `eslint-config-typed`, which this package, published
|
|
18
|
-
* on its own, cannot import.
|
|
19
|
-
*/
|
|
20
|
-
export const skipTypeWrappers = (
|
|
21
|
-
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
22
|
-
node: TSESTree.Node,
|
|
23
|
-
): TSESTree.Node =>
|
|
24
|
-
isTypeWrapper(node) ? skipTypeWrappers(node.expression) : node;
|
|
25
|
-
|
|
26
|
-
export const isTypeWrapper = (
|
|
27
|
-
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
28
|
-
node: TSESTree.Node,
|
|
29
|
-
): node is TypeWrapper => TYPE_WRAPPERS.has(node.type);
|
|
30
|
-
|
|
31
9
|
/**
|
|
32
10
|
* Whether `node`, read through its type wrappers, is the identifier `name`:
|
|
33
11
|
* `Number`, `(Number as NumberConstructor)` and `Number!` are the same object.
|
|
@@ -44,12 +22,6 @@ export const isIdentifierNamed = (
|
|
|
44
22
|
);
|
|
45
23
|
};
|
|
46
24
|
|
|
47
|
-
export type TypeWrapper =
|
|
48
|
-
| TSESTree.TSAsExpression
|
|
49
|
-
| TSESTree.TSNonNullExpression
|
|
50
|
-
| TSESTree.TSSatisfiesExpression
|
|
51
|
-
| TSESTree.TSTypeAssertion;
|
|
52
|
-
|
|
53
25
|
/**
|
|
54
26
|
* The type of the value `node` evaluates to, asked of the expression inside
|
|
55
27
|
* its type wrappers rather than of the cast, or `undefined` without type
|
|
@@ -77,60 +49,6 @@ export const getValueType = (
|
|
|
77
49
|
return hasNonNullAssertion(node) ? checker.getNonNullableType(type) : type;
|
|
78
50
|
};
|
|
79
51
|
|
|
80
|
-
/**
|
|
81
|
-
* The source text of `node` to put in a call's argument list. `getText`
|
|
82
|
-
* leaves out the parentheses the source puts around a node, and a sequence
|
|
83
|
-
* `(a, b)` without them would be read as two arguments.
|
|
84
|
-
*/
|
|
85
|
-
export const getArgumentText = (
|
|
86
|
-
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
87
|
-
sourceCode: TSESLint.SourceCode,
|
|
88
|
-
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
89
|
-
node: TSESTree.Node,
|
|
90
|
-
): string => {
|
|
91
|
-
const text = sourceCode.getText(node);
|
|
92
|
-
|
|
93
|
-
return node.type === AST_NODE_TYPES.SequenceExpression ? `(${text})` : text;
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* The range of `node` together with the parentheses the source puts around it,
|
|
98
|
-
* which `node.range` leaves out: all of `((Array.isArray))` for the member
|
|
99
|
-
* expression inside.
|
|
100
|
-
*/
|
|
101
|
-
export const getRangeWithParens = (
|
|
102
|
-
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
103
|
-
sourceCode: TSESLint.SourceCode,
|
|
104
|
-
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
105
|
-
node: TSESTree.Node,
|
|
106
|
-
): TSESTree.Range => {
|
|
107
|
-
const depth = parenthesesDepth(sourceCode, node);
|
|
108
|
-
|
|
109
|
-
if (depth === 0) {
|
|
110
|
-
return node.range;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
const opening = sourceCode.getTokenBefore(node, { skip: depth - 1 });
|
|
114
|
-
|
|
115
|
-
const closing = sourceCode.getTokenAfter(node, { skip: depth - 1 });
|
|
116
|
-
|
|
117
|
-
return opening === null || closing === null
|
|
118
|
-
? node.range
|
|
119
|
-
: [opening.range[0], closing.range[1]];
|
|
120
|
-
};
|
|
121
|
-
|
|
122
|
-
/** How many pairs of parentheses the source puts around `node`. */
|
|
123
|
-
const parenthesesDepth = (
|
|
124
|
-
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
125
|
-
sourceCode: TSESLint.SourceCode,
|
|
126
|
-
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
127
|
-
node: TSESTree.Node,
|
|
128
|
-
depth: number = 0,
|
|
129
|
-
): number =>
|
|
130
|
-
ASTUtils.isParenthesized(depth + 1, node, sourceCode)
|
|
131
|
-
? parenthesesDepth(sourceCode, node, depth + 1)
|
|
132
|
-
: depth;
|
|
133
|
-
|
|
134
52
|
const hasNonNullAssertion = (
|
|
135
53
|
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
136
54
|
node: TSESTree.Node,
|
|
@@ -138,10 +56,3 @@ const hasNonNullAssertion = (
|
|
|
138
56
|
isTypeWrapper(node) &&
|
|
139
57
|
(node.type === AST_NODE_TYPES.TSNonNullExpression ||
|
|
140
58
|
hasNonNullAssertion(node.expression));
|
|
141
|
-
|
|
142
|
-
const TYPE_WRAPPERS: ReadonlySet<AST_NODE_TYPES> = new Set([
|
|
143
|
-
AST_NODE_TYPES.TSAsExpression,
|
|
144
|
-
AST_NODE_TYPES.TSNonNullExpression,
|
|
145
|
-
AST_NODE_TYPES.TSSatisfiesExpression,
|
|
146
|
-
AST_NODE_TYPES.TSTypeAssertion,
|
|
147
|
-
]);
|
|
@@ -3,12 +3,13 @@ import {
|
|
|
3
3
|
type TSESLint,
|
|
4
4
|
type TSESTree,
|
|
5
5
|
} from '@typescript-eslint/utils';
|
|
6
|
-
import { skipTypeWrappers } from './ast-utils.mjs';
|
|
7
6
|
import {
|
|
8
|
-
|
|
7
|
+
buildNamedImportFix,
|
|
8
|
+
getImportDeclarations,
|
|
9
9
|
getNamedImports,
|
|
10
|
-
|
|
11
|
-
} from '
|
|
10
|
+
skipTypeWrappers,
|
|
11
|
+
} from 'eslint-rule-forge';
|
|
12
|
+
import { TS_STD_FORGE_MODULE } from './constants.mjs';
|
|
12
13
|
|
|
13
14
|
type Options = readonly [];
|
|
14
15
|
|
|
@@ -34,7 +35,10 @@ export const preferIsNonNullObject: TSESLint.RuleModule<MessageIds, Options> = {
|
|
|
34
35
|
|
|
35
36
|
const program = sourceCode.ast;
|
|
36
37
|
|
|
37
|
-
const
|
|
38
|
+
const tsStdForgeImports = getImportDeclarations(
|
|
39
|
+
program,
|
|
40
|
+
TS_STD_FORGE_MODULE,
|
|
41
|
+
);
|
|
38
42
|
|
|
39
43
|
const mut_nodesToFix: {
|
|
40
44
|
node: TSESTree.LogicalExpression;
|
|
@@ -53,7 +57,7 @@ export const preferIsNonNullObject: TSESLint.RuleModule<MessageIds, Options> = {
|
|
|
53
57
|
},
|
|
54
58
|
'Program:exit': () => {
|
|
55
59
|
const hasIsNonNullObjectImport =
|
|
56
|
-
getNamedImports(
|
|
60
|
+
getNamedImports(tsStdForgeImports).includes('isNonNullObject');
|
|
57
61
|
|
|
58
62
|
// The import fix lives on the first report only:
|
|
59
63
|
// `insertTextBefore(program, …)` produces overlapping ranges
|
|
@@ -72,7 +76,9 @@ export const preferIsNonNullObject: TSESLint.RuleModule<MessageIds, Options> = {
|
|
|
72
76
|
|
|
73
77
|
const importFixes =
|
|
74
78
|
index === 0 && !hasIsNonNullObjectImport
|
|
75
|
-
?
|
|
79
|
+
? buildNamedImportFix(fixer, program, TS_STD_FORGE_MODULE, [
|
|
80
|
+
'isNonNullObject',
|
|
81
|
+
])
|
|
76
82
|
: [];
|
|
77
83
|
|
|
78
84
|
return [...importFixes, fixer.replaceText(node, replacement)];
|
|
@@ -3,19 +3,17 @@ import {
|
|
|
3
3
|
type TSESLint,
|
|
4
4
|
type TSESTree,
|
|
5
5
|
} from '@typescript-eslint/utils';
|
|
6
|
-
import { SafeArray } from 'ts-std-forge';
|
|
7
|
-
import * as ts from 'typescript';
|
|
8
6
|
import {
|
|
7
|
+
buildNamedImportFix,
|
|
9
8
|
getArgumentText,
|
|
10
|
-
|
|
11
|
-
isIdentifierNamed,
|
|
12
|
-
skipTypeWrappers,
|
|
13
|
-
} from './ast-utils.mjs';
|
|
14
|
-
import {
|
|
15
|
-
buildImportFixes,
|
|
9
|
+
getImportDeclarations,
|
|
16
10
|
getNamedImports,
|
|
17
|
-
|
|
18
|
-
} from '
|
|
11
|
+
skipTypeWrappers,
|
|
12
|
+
} from 'eslint-rule-forge';
|
|
13
|
+
import { SafeArray } from 'ts-std-forge';
|
|
14
|
+
import * as ts from 'typescript';
|
|
15
|
+
import { getValueType, isIdentifierNamed } from './ast-utils.mjs';
|
|
16
|
+
import { TS_STD_FORGE_MODULE } from './constants.mjs';
|
|
19
17
|
|
|
20
18
|
type Options = readonly [];
|
|
21
19
|
|
|
@@ -44,7 +42,10 @@ export const preferIsRecordAndHasKey: TSESLint.RuleModule<MessageIds, Options> =
|
|
|
44
42
|
|
|
45
43
|
const program = sourceCode.ast;
|
|
46
44
|
|
|
47
|
-
const
|
|
45
|
+
const tsStdForgeImports = getImportDeclarations(
|
|
46
|
+
program,
|
|
47
|
+
TS_STD_FORGE_MODULE,
|
|
48
|
+
);
|
|
48
49
|
|
|
49
50
|
const checker = sourceCode.parserServices?.program?.getTypeChecker();
|
|
50
51
|
|
|
@@ -139,7 +140,7 @@ export const preferIsRecordAndHasKey: TSESLint.RuleModule<MessageIds, Options> =
|
|
|
139
140
|
},
|
|
140
141
|
|
|
141
142
|
'Program:exit': () => {
|
|
142
|
-
const namedImports = getNamedImports(
|
|
143
|
+
const namedImports = getNamedImports(tsStdForgeImports);
|
|
143
144
|
|
|
144
145
|
const rewrites = mut_nodesToFix.map((entry) => ({
|
|
145
146
|
...entry,
|
|
@@ -184,7 +185,12 @@ export const preferIsRecordAndHasKey: TSESLint.RuleModule<MessageIds, Options> =
|
|
|
184
185
|
// otherwise and only one of them would survive a pass.
|
|
185
186
|
const importFixes =
|
|
186
187
|
index === 0 && importsToAdd.length > 0
|
|
187
|
-
?
|
|
188
|
+
? buildNamedImportFix(
|
|
189
|
+
fixer,
|
|
190
|
+
program,
|
|
191
|
+
TS_STD_FORGE_MODULE,
|
|
192
|
+
importsToAdd,
|
|
193
|
+
)
|
|
188
194
|
: [];
|
|
189
195
|
|
|
190
196
|
return [...importFixes, fixer.replaceText(node, replacement)];
|
|
@@ -4,15 +4,14 @@ import {
|
|
|
4
4
|
type TSESTree,
|
|
5
5
|
} from '@typescript-eslint/utils';
|
|
6
6
|
import {
|
|
7
|
+
buildNamedImportFix,
|
|
8
|
+
getImportDeclarations,
|
|
9
|
+
getNamedImports,
|
|
7
10
|
getRangeWithParens,
|
|
8
|
-
isIdentifierNamed,
|
|
9
11
|
skipTypeWrappers,
|
|
10
|
-
} from '
|
|
11
|
-
import {
|
|
12
|
-
|
|
13
|
-
getNamedImports,
|
|
14
|
-
getTsStdForgeImport,
|
|
15
|
-
} from './import-utils.mjs';
|
|
12
|
+
} from 'eslint-rule-forge';
|
|
13
|
+
import { isIdentifierNamed } from './ast-utils.mjs';
|
|
14
|
+
import { TS_STD_FORGE_MODULE } from './constants.mjs';
|
|
16
15
|
|
|
17
16
|
type Options = readonly [];
|
|
18
17
|
|
|
@@ -39,7 +38,10 @@ export const preferSafeArrayIsArray: TSESLint.RuleModule<MessageIds, Options> =
|
|
|
39
38
|
|
|
40
39
|
const program = sourceCode.ast;
|
|
41
40
|
|
|
42
|
-
const
|
|
41
|
+
const tsStdForgeImports = getImportDeclarations(
|
|
42
|
+
program,
|
|
43
|
+
TS_STD_FORGE_MODULE,
|
|
44
|
+
);
|
|
43
45
|
|
|
44
46
|
const mut_nodesToFix: TSESTree.CallExpression[] = [];
|
|
45
47
|
|
|
@@ -53,7 +55,7 @@ export const preferSafeArrayIsArray: TSESLint.RuleModule<MessageIds, Options> =
|
|
|
53
55
|
},
|
|
54
56
|
'Program:exit': () => {
|
|
55
57
|
const hasSafeArrayImport =
|
|
56
|
-
getNamedImports(
|
|
58
|
+
getNamedImports(tsStdForgeImports).includes('SafeArray');
|
|
57
59
|
|
|
58
60
|
// The import fix lives on the first report only:
|
|
59
61
|
// `insertTextBefore(program, …)` produces overlapping ranges
|
|
@@ -67,7 +69,9 @@ export const preferSafeArrayIsArray: TSESLint.RuleModule<MessageIds, Options> =
|
|
|
67
69
|
fix: (fixer) => {
|
|
68
70
|
const importFixes =
|
|
69
71
|
index === 0 && !hasSafeArrayImport
|
|
70
|
-
?
|
|
72
|
+
? buildNamedImportFix(fixer, program, TS_STD_FORGE_MODULE, [
|
|
73
|
+
'SafeArray',
|
|
74
|
+
])
|
|
71
75
|
: [];
|
|
72
76
|
|
|
73
77
|
// Only the callee is replaced, type wrappers included, along
|
|
@@ -45,6 +45,20 @@ ruleTester.run('prefer-safe-array-is-array', preferSafeArrayIsArray, {
|
|
|
45
45
|
`,
|
|
46
46
|
errors: [{ messageId: 'useSafeArrayIsArray' }],
|
|
47
47
|
},
|
|
48
|
+
{
|
|
49
|
+
name: 'Sees SafeArray imported by a second ts-std-forge declaration',
|
|
50
|
+
code: dedent`
|
|
51
|
+
import type { Result } from 'ts-std-forge';
|
|
52
|
+
import { SafeArray } from 'ts-std-forge';
|
|
53
|
+
const result = Array.isArray(value);
|
|
54
|
+
`,
|
|
55
|
+
output: dedent`
|
|
56
|
+
import type { Result } from 'ts-std-forge';
|
|
57
|
+
import { SafeArray } from 'ts-std-forge';
|
|
58
|
+
const result = SafeArray.isArray(value);
|
|
59
|
+
`,
|
|
60
|
+
errors: [{ messageId: 'useSafeArrayIsArray' }],
|
|
61
|
+
},
|
|
48
62
|
{
|
|
49
63
|
name: 'Replace multiple Array.isArray calls, importing once',
|
|
50
64
|
code: dedent`
|
|
@@ -3,17 +3,16 @@ import {
|
|
|
3
3
|
type TSESLint,
|
|
4
4
|
type TSESTree,
|
|
5
5
|
} from '@typescript-eslint/utils';
|
|
6
|
-
import type { ReadonlyRecord } from 'ts-type-forge';
|
|
7
6
|
import {
|
|
7
|
+
buildNamedImportFix,
|
|
8
8
|
getArgumentText,
|
|
9
|
-
|
|
10
|
-
skipTypeWrappers,
|
|
11
|
-
} from './ast-utils.mjs';
|
|
12
|
-
import {
|
|
13
|
-
buildImportFixes,
|
|
9
|
+
getImportDeclarations,
|
|
14
10
|
getNamedImports,
|
|
15
|
-
|
|
16
|
-
} from '
|
|
11
|
+
skipTypeWrappers,
|
|
12
|
+
} from 'eslint-rule-forge';
|
|
13
|
+
import type { ReadonlyRecord } from 'ts-type-forge';
|
|
14
|
+
import { getValueType } from './ast-utils.mjs';
|
|
15
|
+
import { TS_STD_FORGE_MODULE } from './constants.mjs';
|
|
17
16
|
|
|
18
17
|
type Options = readonly [];
|
|
19
18
|
|
|
@@ -82,7 +81,10 @@ export const preferSafeArrayLengthGuard: TSESLint.RuleModule<
|
|
|
82
81
|
|
|
83
82
|
const program = sourceCode.ast;
|
|
84
83
|
|
|
85
|
-
const
|
|
84
|
+
const tsStdForgeImports = getImportDeclarations(
|
|
85
|
+
program,
|
|
86
|
+
TS_STD_FORGE_MODULE,
|
|
87
|
+
);
|
|
86
88
|
|
|
87
89
|
const checker = sourceCode.parserServices?.program?.getTypeChecker();
|
|
88
90
|
|
|
@@ -130,7 +132,7 @@ export const preferSafeArrayLengthGuard: TSESLint.RuleModule<
|
|
|
130
132
|
},
|
|
131
133
|
'Program:exit': () => {
|
|
132
134
|
const hasSafeArrayImport =
|
|
133
|
-
getNamedImports(
|
|
135
|
+
getNamedImports(tsStdForgeImports).includes('SafeArray');
|
|
134
136
|
|
|
135
137
|
// The import fix lives on the first report only:
|
|
136
138
|
// `insertTextBefore(program, …)` produces overlapping ranges
|
|
@@ -155,7 +157,9 @@ export const preferSafeArrayLengthGuard: TSESLint.RuleModule<
|
|
|
155
157
|
|
|
156
158
|
const importFixes =
|
|
157
159
|
index === 0 && !hasSafeArrayImport
|
|
158
|
-
?
|
|
160
|
+
? buildNamedImportFix(fixer, program, TS_STD_FORGE_MODULE, [
|
|
161
|
+
'SafeArray',
|
|
162
|
+
])
|
|
159
163
|
: [];
|
|
160
164
|
|
|
161
165
|
return [...importFixes, fixer.replaceText(node, replacement)];
|
|
@@ -3,18 +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
8
|
getArgumentText,
|
|
9
|
-
|
|
10
|
-
isIdentifierNamed,
|
|
11
|
-
skipTypeWrappers,
|
|
12
|
-
} from './ast-utils.mjs';
|
|
13
|
-
import {
|
|
14
|
-
buildImportFixes,
|
|
9
|
+
getImportDeclarations,
|
|
15
10
|
getNamedImports,
|
|
16
|
-
|
|
17
|
-
} from '
|
|
11
|
+
skipTypeWrappers,
|
|
12
|
+
} from 'eslint-rule-forge';
|
|
13
|
+
import * as ts from 'typescript';
|
|
14
|
+
import { getValueType, isIdentifierNamed } from './ast-utils.mjs';
|
|
15
|
+
import { TS_STD_FORGE_MODULE } from './constants.mjs';
|
|
18
16
|
|
|
19
17
|
type Options = readonly [];
|
|
20
18
|
|
|
@@ -66,7 +64,10 @@ export const preferSafeNumberParseInteger: TSESLint.RuleModule<
|
|
|
66
64
|
|
|
67
65
|
const program = sourceCode.ast;
|
|
68
66
|
|
|
69
|
-
const
|
|
67
|
+
const tsStdForgeImports = getImportDeclarations(
|
|
68
|
+
program,
|
|
69
|
+
TS_STD_FORGE_MODULE,
|
|
70
|
+
);
|
|
70
71
|
|
|
71
72
|
const mut_nodesToFix: {
|
|
72
73
|
node: TSESTree.CallExpression;
|
|
@@ -130,7 +131,7 @@ export const preferSafeNumberParseInteger: TSESLint.RuleModule<
|
|
|
130
131
|
mut_nodesToFix.push({ node, argExpression: firstArg });
|
|
131
132
|
},
|
|
132
133
|
'Program:exit': () => {
|
|
133
|
-
const namedImports = getNamedImports(
|
|
134
|
+
const namedImports = getNamedImports(tsStdForgeImports);
|
|
134
135
|
|
|
135
136
|
const missingImports = (['Result', 'SafeNumber'] as const).filter(
|
|
136
137
|
(name) => !namedImports.includes(name),
|
|
@@ -154,7 +155,12 @@ export const preferSafeNumberParseInteger: TSESLint.RuleModule<
|
|
|
154
155
|
|
|
155
156
|
const importFixes =
|
|
156
157
|
index === 0 && missingImports.length > 0
|
|
157
|
-
?
|
|
158
|
+
? buildNamedImportFix(
|
|
159
|
+
fixer,
|
|
160
|
+
program,
|
|
161
|
+
TS_STD_FORGE_MODULE,
|
|
162
|
+
missingImports,
|
|
163
|
+
)
|
|
158
164
|
: [];
|
|
159
165
|
|
|
160
166
|
return [...importFixes, fixer.replaceText(node, core)];
|
|
@@ -3,18 +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
8
|
getArgumentText,
|
|
9
|
-
|
|
10
|
-
isIdentifierNamed,
|
|
11
|
-
skipTypeWrappers,
|
|
12
|
-
} from './ast-utils.mjs';
|
|
13
|
-
import {
|
|
14
|
-
buildImportFixes,
|
|
9
|
+
getImportDeclarations,
|
|
15
10
|
getNamedImports,
|
|
16
|
-
|
|
17
|
-
} from '
|
|
11
|
+
skipTypeWrappers,
|
|
12
|
+
} from 'eslint-rule-forge';
|
|
13
|
+
import * as ts from 'typescript';
|
|
14
|
+
import { getValueType, isIdentifierNamed } from './ast-utils.mjs';
|
|
15
|
+
import { TS_STD_FORGE_MODULE } from './constants.mjs';
|
|
18
16
|
|
|
19
17
|
type Options = readonly [];
|
|
20
18
|
|
|
@@ -69,7 +67,10 @@ export const preferSafeNumberParse: TSESLint.RuleModule<MessageIds, Options> = {
|
|
|
69
67
|
|
|
70
68
|
const program = sourceCode.ast;
|
|
71
69
|
|
|
72
|
-
const
|
|
70
|
+
const tsStdForgeImports = getImportDeclarations(
|
|
71
|
+
program,
|
|
72
|
+
TS_STD_FORGE_MODULE,
|
|
73
|
+
);
|
|
73
74
|
|
|
74
75
|
const mut_nodesToFix: {
|
|
75
76
|
node: TSESTree.CallExpression;
|
|
@@ -127,7 +128,7 @@ export const preferSafeNumberParse: TSESLint.RuleModule<MessageIds, Options> = {
|
|
|
127
128
|
mut_nodesToFix.push({ node, argExpression: firstArg });
|
|
128
129
|
},
|
|
129
130
|
'Program:exit': () => {
|
|
130
|
-
const namedImports = getNamedImports(
|
|
131
|
+
const namedImports = getNamedImports(tsStdForgeImports);
|
|
131
132
|
|
|
132
133
|
const missingImports = (['Result', 'SafeNumber'] as const).filter(
|
|
133
134
|
(name) => !namedImports.includes(name),
|
|
@@ -151,7 +152,12 @@ export const preferSafeNumberParse: TSESLint.RuleModule<MessageIds, Options> = {
|
|
|
151
152
|
|
|
152
153
|
const importFixes =
|
|
153
154
|
index === 0 && missingImports.length > 0
|
|
154
|
-
?
|
|
155
|
+
? buildNamedImportFix(
|
|
156
|
+
fixer,
|
|
157
|
+
program,
|
|
158
|
+
TS_STD_FORGE_MODULE,
|
|
159
|
+
missingImports,
|
|
160
|
+
)
|
|
155
161
|
: [];
|
|
156
162
|
|
|
157
163
|
return [...importFixes, fixer.replaceText(node, core)];
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import { type TSESLint, type TSESTree } from '@typescript-eslint/utils';
|
|
2
|
-
import type { DeepReadonly } from 'ts-type-forge';
|
|
3
|
-
export declare const getTsStdForgeImport: (program: TSESTree.Program) => TSESTree.ImportDeclaration | undefined;
|
|
4
|
-
export declare const getNamedImports: (node: DeepReadonly<TSESTree.ImportDeclaration> | undefined) => readonly string[];
|
|
5
|
-
export declare const buildImportFixes: (fixer: TSESLint.RuleFixer, program: TSESTree.Program, requiredNames: readonly string[]) => readonly TSESLint.RuleFix[];
|
|
6
|
-
//# 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;AAKlD,eAAO,MAAM,mBAAmB,YACrB,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,eAAO,MAAM,gBAAgB,UACpB,QAAQ,CAAC,SAAS,WAChB,QAAQ,CAAC,OAAO,iBACV,SAAS,MAAM,EAAE,KAC/B,SAAS,QAAQ,CAAC,OAAO,EAa3B,CAAC"}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { AST_NODE_TYPES, } from '@typescript-eslint/utils';
|
|
2
|
-
import { TS_STD_FORGE_MODULE } from './constants.mjs';
|
|
3
|
-
|
|
4
|
-
export const getTsStdForgeImport = (program) => program.body.find((node) => node.type === AST_NODE_TYPES.ImportDeclaration &&
|
|
5
|
-
node.source.value === TS_STD_FORGE_MODULE);
|
|
6
|
-
export const getNamedImports = (node) => {
|
|
7
|
-
if (node === undefined) {
|
|
8
|
-
return [];
|
|
9
|
-
}
|
|
10
|
-
return node.specifiers.flatMap((specifier) => specifier.type === AST_NODE_TYPES.ImportSpecifier
|
|
11
|
-
? (() => {
|
|
12
|
-
const importedName = specifier.imported.type === AST_NODE_TYPES.Identifier
|
|
13
|
-
? specifier.imported.name
|
|
14
|
-
: specifier.imported.value;
|
|
15
|
-
return typeof importedName === 'string' ? [importedName] : [];
|
|
16
|
-
})()
|
|
17
|
-
: []);
|
|
18
|
-
};
|
|
19
|
-
export const buildImportFixes = (fixer, program, requiredNames) => {
|
|
20
|
-
const specifierText = requiredNames.join(', ');
|
|
21
|
-
const importStatement = `import { ${specifierText} } from '${TS_STD_FORGE_MODULE}';`;
|
|
22
|
-
const newLine = '\n';
|
|
23
|
-
const insertionText = `${importStatement}${newLine}`;
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
return [fixer.insertTextBefore(program, insertionText)];
|
|
27
|
-
};
|
|
28
|
-
//# 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,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAEtD,uEAAuE;AAEvE,MAAM,CAAC,MAAM,mBAAmB,GAAG,CACjC,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,mBAAmB,CAC5C,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,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAC9B,KAAyB,EACzB,OAAyB,EACzB,aAAgC,EACH,EAAE;IAC/B,MAAM,aAAa,GAAG,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAE/C,MAAM,eAAe,GACnB,YAAY,aAAa,YAAY,mBAAmB,IAAa,CAAC;IAExE,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,58 +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 { TS_STD_FORGE_MODULE } from './constants.mjs';
|
|
8
|
-
|
|
9
|
-
/* eslint-disable @typescript-eslint/prefer-readonly-parameter-types */
|
|
10
|
-
|
|
11
|
-
export const getTsStdForgeImport = (
|
|
12
|
-
program: TSESTree.Program,
|
|
13
|
-
): TSESTree.ImportDeclaration | undefined =>
|
|
14
|
-
program.body.find(
|
|
15
|
-
(node): node is TSESTree.ImportDeclaration =>
|
|
16
|
-
node.type === AST_NODE_TYPES.ImportDeclaration &&
|
|
17
|
-
node.source.value === TS_STD_FORGE_MODULE,
|
|
18
|
-
);
|
|
19
|
-
|
|
20
|
-
export const getNamedImports = (
|
|
21
|
-
node: DeepReadonly<TSESTree.ImportDeclaration> | undefined,
|
|
22
|
-
): readonly string[] => {
|
|
23
|
-
if (node === undefined) {
|
|
24
|
-
return [];
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
return node.specifiers.flatMap((specifier) =>
|
|
28
|
-
specifier.type === AST_NODE_TYPES.ImportSpecifier
|
|
29
|
-
? (() => {
|
|
30
|
-
const importedName =
|
|
31
|
-
specifier.imported.type === AST_NODE_TYPES.Identifier
|
|
32
|
-
? specifier.imported.name
|
|
33
|
-
: specifier.imported.value;
|
|
34
|
-
|
|
35
|
-
return typeof importedName === 'string' ? [importedName] : [];
|
|
36
|
-
})()
|
|
37
|
-
: [],
|
|
38
|
-
);
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
export const buildImportFixes = (
|
|
42
|
-
fixer: TSESLint.RuleFixer,
|
|
43
|
-
program: TSESTree.Program,
|
|
44
|
-
requiredNames: readonly string[],
|
|
45
|
-
): readonly TSESLint.RuleFix[] => {
|
|
46
|
-
const specifierText = requiredNames.join(', ');
|
|
47
|
-
|
|
48
|
-
const importStatement =
|
|
49
|
-
`import { ${specifierText} } from '${TS_STD_FORGE_MODULE}';` as const;
|
|
50
|
-
|
|
51
|
-
const newLine = '\n';
|
|
52
|
-
|
|
53
|
-
const insertionText = `${importStatement}${newLine}` as const;
|
|
54
|
-
|
|
55
|
-
// Always insert at the beginning of the file
|
|
56
|
-
// (organize-imports will handle merging/deduplication)
|
|
57
|
-
return [fixer.insertTextBefore(program, insertionText)];
|
|
58
|
-
};
|