eslint-plugin-ts-data-forge 0.10.5 → 0.10.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/rules/ast-utils.d.mts +5 -5
- package/dist/rules/ast-utils.d.mts.map +1 -1
- package/dist/rules/ast-utils.mjs +3 -3
- package/dist/rules/ast-utils.mjs.map +1 -1
- package/dist/rules/import-binding.d.mts +38 -0
- package/dist/rules/import-binding.d.mts.map +1 -0
- package/dist/rules/import-binding.mjs +53 -0
- package/dist/rules/import-binding.mjs.map +1 -0
- package/dist/rules/mutable-result.mjs +37 -37
- package/dist/rules/mutable-result.mjs.map +1 -1
- package/dist/rules/no-unnecessary-type-guard.d.mts.map +1 -1
- package/dist/rules/no-unnecessary-type-guard.mjs +146 -143
- package/dist/rules/no-unnecessary-type-guard.mjs.map +1 -1
- package/dist/rules/prefer-arr-generate.d.mts.map +1 -1
- package/dist/rules/prefer-arr-generate.mjs +129 -131
- package/dist/rules/prefer-arr-generate.mjs.map +1 -1
- package/dist/rules/prefer-arr-is-bounded-length-array.d.mts.map +1 -1
- package/dist/rules/prefer-arr-is-bounded-length-array.mjs +14 -16
- package/dist/rules/prefer-arr-is-bounded-length-array.mjs.map +1 -1
- package/dist/rules/prefer-arr-is-fixed-length-array.d.mts.map +1 -1
- package/dist/rules/prefer-arr-is-fixed-length-array.mjs +15 -17
- package/dist/rules/prefer-arr-is-fixed-length-array.mjs.map +1 -1
- package/dist/rules/prefer-arr-is-max-length-array.d.mts.map +1 -1
- package/dist/rules/prefer-arr-is-max-length-array.mjs +14 -16
- package/dist/rules/prefer-arr-is-max-length-array.mjs.map +1 -1
- package/dist/rules/prefer-arr-is-min-length-array.d.mts.map +1 -1
- package/dist/rules/prefer-arr-is-min-length-array.mjs +14 -16
- package/dist/rules/prefer-arr-is-min-length-array.mjs.map +1 -1
- package/dist/rules/prefer-arr-is-non-empty.d.mts.map +1 -1
- package/dist/rules/prefer-arr-is-non-empty.mjs +14 -16
- package/dist/rules/prefer-arr-is-non-empty.mjs.map +1 -1
- package/dist/rules/prefer-arr-scan.d.mts.map +1 -1
- package/dist/rules/prefer-arr-scan.mjs +9 -18
- package/dist/rules/prefer-arr-scan.mjs.map +1 -1
- package/dist/rules/prefer-arr-sum.d.mts.map +1 -1
- package/dist/rules/prefer-arr-sum.mjs +16 -21
- package/dist/rules/prefer-arr-sum.mjs.map +1 -1
- package/dist/rules/prefer-arr-uniq.d.mts.map +1 -1
- package/dist/rules/prefer-arr-uniq.mjs +38 -43
- package/dist/rules/prefer-arr-uniq.mjs.map +1 -1
- package/dist/rules/prefer-as-int.d.mts.map +1 -1
- package/dist/rules/prefer-as-int.mjs +19 -26
- package/dist/rules/prefer-as-int.mjs.map +1 -1
- package/dist/rules/prefer-canonical-array-slicing.d.mts.map +1 -1
- package/dist/rules/prefer-canonical-array-slicing.mjs +49 -15
- package/dist/rules/prefer-canonical-array-slicing.mjs.map +1 -1
- package/dist/rules/prefer-canonical-length-cast.mjs +15 -15
- package/dist/rules/prefer-canonical-length-cast.mjs.map +1 -1
- package/dist/rules/prefer-obj-over-entries-round-trip.d.mts.map +1 -1
- package/dist/rules/prefer-obj-over-entries-round-trip.mjs +100 -99
- package/dist/rules/prefer-obj-over-entries-round-trip.mjs.map +1 -1
- package/dist/rules/prefer-pipe-map-nullable.d.mts.map +1 -1
- package/dist/rules/prefer-pipe-map-nullable.mjs +2 -4
- package/dist/rules/prefer-pipe-map-nullable.mjs.map +1 -1
- package/dist/rules/prefer-range-for-loop.d.mts.map +1 -1
- package/dist/rules/prefer-range-for-loop.mjs +18 -24
- package/dist/rules/prefer-range-for-loop.mjs.map +1 -1
- package/package.json +4 -4
- package/src/rules/ast-utils.mts +11 -11
- package/src/rules/import-binding.mts +94 -0
- package/src/rules/mutable-result.mts +56 -56
- package/src/rules/no-unnecessary-type-guard.mts +199 -203
- package/src/rules/no-unnecessary-type-guard.test.mts +62 -2
- package/src/rules/prefer-arr-generate.mts +184 -194
- package/src/rules/prefer-arr-generate.test.mts +262 -134
- package/src/rules/prefer-arr-is-bounded-length-array.mts +22 -33
- package/src/rules/prefer-arr-is-fixed-length-array.mts +24 -36
- package/src/rules/prefer-arr-is-fixed-length-array.test.mts +16 -7
- package/src/rules/prefer-arr-is-max-length-array.mts +21 -34
- package/src/rules/prefer-arr-is-max-length-array.test.mts +16 -7
- package/src/rules/prefer-arr-is-min-length-array.mts +21 -34
- package/src/rules/prefer-arr-is-min-length-array.test.mts +16 -7
- package/src/rules/prefer-arr-is-non-empty.mts +17 -34
- package/src/rules/prefer-arr-is-non-empty.test.mts +110 -0
- package/src/rules/prefer-arr-scan.mts +11 -36
- package/src/rules/prefer-arr-scan.test.mts +55 -0
- package/src/rules/prefer-arr-sum.mts +19 -33
- package/src/rules/prefer-arr-uniq.mts +49 -60
- package/src/rules/prefer-arr-uniq.test.mts +46 -20
- package/src/rules/prefer-as-int.mts +27 -52
- package/src/rules/prefer-as-int.test.mts +79 -29
- package/src/rules/prefer-canonical-array-slicing.mts +86 -24
- package/src/rules/prefer-canonical-array-slicing.test.mts +133 -34
- package/src/rules/prefer-canonical-length-cast.mts +18 -18
- package/src/rules/prefer-obj-over-entries-round-trip.mts +152 -170
- package/src/rules/prefer-obj-over-entries-round-trip.test.mts +48 -6
- package/src/rules/prefer-pipe-map-nullable.mts +6 -8
- package/src/rules/prefer-range-for-loop.mts +31 -55
|
@@ -24,11 +24,6 @@ export declare const asLengthAccess: (node: TSESTree.Expression) => TSESTree.Mem
|
|
|
24
24
|
* `xs.length >= 1 && (xs as readonly T[]).length <= 3` bounds one array.
|
|
25
25
|
*/
|
|
26
26
|
export declare const isSameArrayText: (a: TSESTree.Expression, b: TSESTree.Expression, sourceCode: TSESLint.SourceCode) => boolean;
|
|
27
|
-
type LengthComparison = Readonly<{
|
|
28
|
-
array: TSESTree.Expression;
|
|
29
|
-
bound: TSESTree.Expression;
|
|
30
|
-
kind: 'max' | 'min';
|
|
31
|
-
}>;
|
|
32
27
|
/**
|
|
33
28
|
* Parses a `<array>.length <op> <bound>` comparison (in either operand order)
|
|
34
29
|
* into its array expression, integer-literal/`const` `bound`, and whether it is
|
|
@@ -52,5 +47,10 @@ export declare const parseLengthComparison: (wrapped: TSESTree.Expression, sourc
|
|
|
52
47
|
* is still the operand.
|
|
53
48
|
*/
|
|
54
49
|
export declare const isPartOfBoundedLengthCheck: (node: TSESTree.BinaryExpression, sourceCode: TSESLint.SourceCode) => boolean;
|
|
50
|
+
type LengthComparison = Readonly<{
|
|
51
|
+
array: TSESTree.Expression;
|
|
52
|
+
bound: TSESTree.Expression;
|
|
53
|
+
kind: 'max' | 'min';
|
|
54
|
+
}>;
|
|
55
55
|
export {};
|
|
56
56
|
//# 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,EAGL,KAAK,QAAQ,EACb,KAAK,QAAQ,EACd,MAAM,0BAA0B,CAAC;AAMlC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"ast-utils.d.mts","sourceRoot":"","sources":["../../src/rules/ast-utils.mts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,QAAQ,EACb,KAAK,QAAQ,EACd,MAAM,0BAA0B,CAAC;AAMlC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB,aAEzB,QAAQ,CAAC,UAAU,CAAC,gBAAgB,CAAC,QAEzC,QAAQ,CAAC,UAAU,KACxB,OAkBF,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,0BAA0B,SAC/B,YAAY,CAAC,QAAQ,CAAC,UAAU,CAAC,cAE3B,QAAQ,CAAC,UAAU,KAC9B,OA0CF,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,cAAc,SAEnB,QAAQ,CAAC,UAAU,KACxB,QAAQ,CAAC,gBAAgB,GAAG,SAS9B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,eAAe,MAEvB,QAAQ,CAAC,UAAU,KAEnB,QAAQ,CAAC,UAAU,cAEV,QAAQ,CAAC,UAAU,KAC9B,OAEsC,CAAC;AAE1C;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,qBAAqB,YAEvB,QAAQ,CAAC,UAAU,cAEhB,QAAQ,CAAC,UAAU,KAC9B,gBAAgB,GAAG,SAuCrB,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,0BAA0B,SAE/B,QAAQ,CAAC,gBAAgB,cAEnB,QAAQ,CAAC,UAAU,KAC9B,OA8BF,CAAC;AAOF,KAAK,gBAAgB,GAAG,QAAQ,CAAC;IAC/B,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC;IAC3B,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC;IAC3B,IAAI,EAAE,KAAK,GAAG,KAAK,CAAC;CACrB,CAAC,CAAC"}
|
package/dist/rules/ast-utils.mjs
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
import { AST_NODE_TYPES, ASTUtils, } from '@typescript-eslint/utils';
|
|
2
2
|
import { isTypeWrapper, skipTypeWrappers, typeWrapperLayers, } from 'eslint-rule-forge';
|
|
3
|
-
const isIntegerLiteral = (node) => node.type === AST_NODE_TYPES.Literal &&
|
|
4
|
-
typeof node.value === 'number' &&
|
|
5
|
-
Number.isInteger(node.value);
|
|
6
3
|
|
|
7
4
|
|
|
8
5
|
|
|
@@ -169,6 +166,9 @@ sourceCode) => {
|
|
|
169
166
|
return (self.kind !== other.kind &&
|
|
170
167
|
isSameArrayText(self.array, other.array, sourceCode));
|
|
171
168
|
};
|
|
169
|
+
const isIntegerLiteral = (node) => node.type === AST_NODE_TYPES.Literal &&
|
|
170
|
+
typeof node.value === 'number' &&
|
|
171
|
+
Number.isInteger(node.value);
|
|
172
172
|
|
|
173
173
|
const outermostTypeWrapper = (
|
|
174
174
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ast-utils.mjs","sourceRoot":"","sources":["../../src/rules/ast-utils.mts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,QAAQ,GAGT,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,mBAAmB,CAAC;AAG3B
|
|
1
|
+
{"version":3,"file":"ast-utils.mjs","sourceRoot":"","sources":["../../src/rules/ast-utils.mts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { TSESLint, TSESTree } from '@typescript-eslint/utils';
|
|
2
|
+
import { type ValueImportBinding } from 'eslint-rule-forge';
|
|
3
|
+
/**
|
|
4
|
+
* Binds ts-data-forge's `exportName` as a value once per file (see
|
|
5
|
+
* `bindValueImports`), and gives, for the code at a node, the name a fix
|
|
6
|
+
* writes and the edits that bring it into scope, or `undefined` when no fix
|
|
7
|
+
* can: an import already binds the name to something else, or something other
|
|
8
|
+
* than the import takes it where the code is.
|
|
9
|
+
*
|
|
10
|
+
* Every fix that writes the name makes these edits itself, so that one applied
|
|
11
|
+
* alone (an editor's quick fix) is complete; `--fix` then takes one pass per
|
|
12
|
+
* report that adds the import.
|
|
13
|
+
*/
|
|
14
|
+
export declare const tsDataForgeValueAt: (sourceCode: TSESLint.SourceCode, exportName: string) => ((node: TSESTree.Node) => TsDataForgeValue | undefined);
|
|
15
|
+
/**
|
|
16
|
+
* {@link tsDataForgeValueAt} for a name that varies from report to report (a
|
|
17
|
+
* cast function, a replacement guard): each name is bound once per file,
|
|
18
|
+
* however many reports write it.
|
|
19
|
+
*/
|
|
20
|
+
export declare const tsDataForgeValueAtByName: (sourceCode: TSESLint.SourceCode) => ((exportName: string) => ReturnType<typeof tsDataForgeValueAt>);
|
|
21
|
+
/**
|
|
22
|
+
* {@link tsDataForgeValueAt} for several names one fix writes together: their
|
|
23
|
+
* edits are made as one, so that two names the file does not import go into a
|
|
24
|
+
* single new declaration. `localNames` are the names to write, known before
|
|
25
|
+
* any node is: the export names themselves when they cannot be bound.
|
|
26
|
+
*/
|
|
27
|
+
export declare const tsDataForgeValuesAt: (sourceCode: TSESLint.SourceCode, exportNames: readonly string[]) => Readonly<{
|
|
28
|
+
localNames: readonly string[];
|
|
29
|
+
at: (node: TSESTree.Node) => ValueImportBinding | undefined;
|
|
30
|
+
}>;
|
|
31
|
+
/** What {@link tsDataForgeValueAt} gives for one node. */
|
|
32
|
+
export type TsDataForgeValue = Readonly<{
|
|
33
|
+
/** The name to write. */
|
|
34
|
+
localName: string;
|
|
35
|
+
/** The edits that bind it. */
|
|
36
|
+
edits: ValueImportBinding['edits'];
|
|
37
|
+
}>;
|
|
38
|
+
//# sourceMappingURL=import-binding.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"import-binding.d.mts","sourceRoot":"","sources":["../../src/rules/import-binding.mts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,EAGL,KAAK,kBAAkB,EACxB,MAAM,mBAAmB,CAAC;AAI3B;;;;;;;;;;GAUG;AACH,eAAO,MAAM,kBAAkB,eAEjB,QAAQ,CAAC,UAAU,cACnB,MAAM,KAEjB,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,KAAK,gBAAgB,GAAG,SAAS,CAYxD,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,eAEvB,QAAQ,CAAC,UAAU,KAC9B,CAAC,CAAC,UAAU,EAAE,MAAM,KAAK,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAI9D,CAAC;AAEJ;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,eAElB,QAAQ,CAAC,UAAU,eAClB,SAAS,MAAM,EAAE,KAC7B,QAAQ,CAAC;IACV,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IAE9B,EAAE,EAAE,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,KAAK,kBAAkB,GAAG,SAAS,CAAC;CAC7D,CAiBA,CAAC;AAEF,0DAA0D;AAC1D,MAAM,MAAM,gBAAgB,GAAG,QAAQ,CAAC;IACtC,yBAAyB;IACzB,SAAS,EAAE,MAAM,CAAC;IAElB,8BAA8B;IAC9B,KAAK,EAAE,kBAAkB,CAAC,OAAO,CAAC,CAAC;CACpC,CAAC,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { bindValueImports, hasForeignBinding, } from 'eslint-rule-forge';
|
|
2
|
+
import { memoizeFunction } from 'ts-data-forge';
|
|
3
|
+
import { TS_DATA_FORGE_MODULE } from './constants.mjs';
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
export const tsDataForgeValueAt = (
|
|
16
|
+
|
|
17
|
+
sourceCode, exportName) => {
|
|
18
|
+
const { at } = tsDataForgeValuesAt(sourceCode, [exportName]);
|
|
19
|
+
return (node) => {
|
|
20
|
+
const binding = at(node);
|
|
21
|
+
const localName = binding?.localNames[0];
|
|
22
|
+
return binding === undefined || localName === undefined
|
|
23
|
+
? undefined
|
|
24
|
+
: { localName, edits: binding.edits };
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
export const tsDataForgeValueAtByName = (
|
|
33
|
+
|
|
34
|
+
sourceCode) => memoizeFunction((exportName) => tsDataForgeValueAt(sourceCode, exportName), (exportName) => exportName);
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
export const tsDataForgeValuesAt = (
|
|
42
|
+
|
|
43
|
+
sourceCode, exportNames) => {
|
|
44
|
+
const binding = bindValueImports(sourceCode, TS_DATA_FORGE_MODULE, exportNames);
|
|
45
|
+
return {
|
|
46
|
+
localNames: binding?.localNames ?? exportNames,
|
|
47
|
+
at: (node) => binding === undefined ||
|
|
48
|
+
binding.localNames.some((localName) => hasForeignBinding(sourceCode, node, localName, TS_DATA_FORGE_MODULE))
|
|
49
|
+
? undefined
|
|
50
|
+
: binding,
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
//# sourceMappingURL=import-binding.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"import-binding.mjs","sourceRoot":"","sources":["../../src/rules/import-binding.mts"],"names":[],"mappings":"AACA,OAAO,EACL,gBAAgB,EAChB,iBAAiB,GAElB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAEvD;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG;AAChC,8EAA8E;AAC9E,UAA+B,EAC/B,UAAkB,EAEuC,EAAE;IAC3D,MAAM,EAAE,EAAE,EAAE,GAAG,mBAAmB,CAAC,UAAU,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;IAE7D,OAAO,CAAC,IAAI,EAAE,EAAE;QACd,MAAM,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;QAEzB,MAAM,SAAS,GAAG,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC;QAEzC,OAAO,OAAO,KAAK,SAAS,IAAI,SAAS,KAAK,SAAS;YACrD,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC;IAC1C,CAAC,CAAC;AACJ,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG;AACtC,8EAA8E;AAC9E,UAA+B,EACkC,EAAE,CACnE,eAAe,CACb,CAAC,UAAkB,EAAE,EAAE,CAAC,kBAAkB,CAAC,UAAU,EAAE,UAAU,CAAC,EAClE,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAC3B,CAAC;AAEJ;;;;;GAKG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG;AACjC,8EAA8E;AAC9E,UAA+B,EAC/B,WAA8B,EAK7B,EAAE;IACH,MAAM,OAAO,GAAG,gBAAgB,CAC9B,UAAU,EACV,oBAAoB,EACpB,WAAW,CACZ,CAAC;IAEF,OAAO;QACL,UAAU,EAAE,OAAO,EAAE,UAAU,IAAI,WAAW;QAC9C,EAAE,EAAE,CAAC,IAAI,EAAE,EAAE,CACX,OAAO,KAAK,SAAS;YACrB,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CACpC,iBAAiB,CAAC,UAAU,EAAE,IAAI,EAAE,SAAS,EAAE,oBAAoB,CAAC,CACrE;YACC,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,OAAO;KACd,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -48,43 +48,6 @@ node) => {
|
|
|
48
48
|
? outermostTypePreservingWrapper(parent)
|
|
49
49
|
: node;
|
|
50
50
|
};
|
|
51
|
-
const isUsedAsMutable = (
|
|
52
|
-
|
|
53
|
-
checker,
|
|
54
|
-
|
|
55
|
-
getTsNode,
|
|
56
|
-
|
|
57
|
-
node) => {
|
|
58
|
-
const parent = node.parent;
|
|
59
|
-
if (parent?.type === AST_NODE_TYPES.MemberExpression &&
|
|
60
|
-
parent.object === node) {
|
|
61
|
-
|
|
62
|
-
if (!parent.computed &&
|
|
63
|
-
parent.property.type === AST_NODE_TYPES.Identifier &&
|
|
64
|
-
mutatingMethods.has(parent.property.name)) {
|
|
65
|
-
return true;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const grandParent = parent.parent;
|
|
69
|
-
return ((grandParent.type === AST_NODE_TYPES.AssignmentExpression &&
|
|
70
|
-
grandParent.left === parent) ||
|
|
71
|
-
grandParent.type === AST_NODE_TYPES.UpdateExpression ||
|
|
72
|
-
(grandParent.type === AST_NODE_TYPES.UnaryExpression &&
|
|
73
|
-
grandParent.operator === 'delete'));
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
const tsNode = getTsNode(node);
|
|
78
|
-
if (tsNode === undefined) {
|
|
79
|
-
return false;
|
|
80
|
-
}
|
|
81
|
-
if (!ts.isExpression(tsNode)) {
|
|
82
|
-
return false;
|
|
83
|
-
}
|
|
84
|
-
const expectedType = getDeclaredParameterType(checker, tsNode) ??
|
|
85
|
-
checker.getContextualType(tsNode);
|
|
86
|
-
return (expectedType !== undefined && isMutableArrayOnly(checker, expectedType));
|
|
87
|
-
};
|
|
88
51
|
|
|
89
52
|
|
|
90
53
|
|
|
@@ -130,6 +93,43 @@ type) => {
|
|
|
130
93
|
(t.flags & primitiveTypeFlags) !== 0 ||
|
|
131
94
|
(checker.isArrayType(t) && t.getSymbol()?.getName() === 'Array')) && members.some((t) => (t.flags & primitiveTypeFlags) === 0));
|
|
132
95
|
};
|
|
96
|
+
const isUsedAsMutable = (
|
|
97
|
+
|
|
98
|
+
checker,
|
|
99
|
+
|
|
100
|
+
getTsNode,
|
|
101
|
+
|
|
102
|
+
node) => {
|
|
103
|
+
const parent = node.parent;
|
|
104
|
+
if (parent?.type === AST_NODE_TYPES.MemberExpression &&
|
|
105
|
+
parent.object === node) {
|
|
106
|
+
|
|
107
|
+
if (!parent.computed &&
|
|
108
|
+
parent.property.type === AST_NODE_TYPES.Identifier &&
|
|
109
|
+
mutatingMethods.has(parent.property.name)) {
|
|
110
|
+
return true;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const grandParent = parent.parent;
|
|
114
|
+
return ((grandParent.type === AST_NODE_TYPES.AssignmentExpression &&
|
|
115
|
+
grandParent.left === parent) ||
|
|
116
|
+
grandParent.type === AST_NODE_TYPES.UpdateExpression ||
|
|
117
|
+
(grandParent.type === AST_NODE_TYPES.UnaryExpression &&
|
|
118
|
+
grandParent.operator === 'delete'));
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
const tsNode = getTsNode(node);
|
|
123
|
+
if (tsNode === undefined) {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
if (!ts.isExpression(tsNode)) {
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
const expectedType = getDeclaredParameterType(checker, tsNode) ??
|
|
130
|
+
checker.getContextualType(tsNode);
|
|
131
|
+
return (expectedType !== undefined && isMutableArrayOnly(checker, expectedType));
|
|
132
|
+
};
|
|
133
133
|
|
|
134
134
|
const mutatingMethods = new Set([
|
|
135
135
|
'copyWithin',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mutable-result.mjs","sourceRoot":"","sources":["../../src/rules/mutable-result.mts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,GAGf,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AACjC,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAErD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG;AAChC,8EAA8E;AAC9E,UAA+B;AAC/B,8EAA8E;AAC9E,OAAuB;AACvB,8EAA8E;AAC9E,SAAyD;AACzD,8EAA8E;AAC9E,IAAmB,EACV,EAAE;IACX,MAAM,KAAK,GAAG,8BAA8B,CAAC,IAAI,CAAC,CAAC;IAEnD,IAAI,eAAe,CAAC,OAAO,EAAE,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC;QAC/C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;IAE5B,IACE,MAAM,EAAE,IAAI,KAAK,cAAc,CAAC,kBAAkB;QAClD,MAAM,CAAC,IAAI,KAAK,KAAK;QACrB,MAAM,CAAC,EAAE,CAAC,IAAI,KAAK,cAAc,CAAC,UAAU;QAC5C,MAAM,CAAC,EAAE,CAAC,cAAc,KAAK,SAAS,EACtC,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,CAAC,QAAQ,CAAC,GAAG,UAAU,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAE3D,OAAO,CACL,QAAQ,EAAE,UAAU,CAAC,IAAI,CACvB,CAAC,SAAS,EAAE,EAAE,CACZ,SAAS,CAAC,IAAI,KAAK,IAAI;QACvB,eAAe,CACb,OAAO,EACP,SAAS,EACT,8BAA8B,CAAC,SAAS,CAAC,UAAU,CAAC,CACrD,CACJ,IAAI,KAAK,CACX,CAAC;AACJ,CAAC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,8BAA8B,GAAG;AACrC,8EAA8E;AAC9E,IAAmB,EACJ,EAAE;IACjB,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAExB,OAAO,MAAM,KAAK,SAAS;QACzB,CAAC,MAAM,CAAC,IAAI,KAAK,cAAc,CAAC,mBAAmB;YACjD,MAAM,CAAC,IAAI,KAAK,cAAc,CAAC,qBAAqB,CAAC;QACvD,MAAM,CAAC,UAAU,KAAK,IAAI;QAC1B,CAAC,CAAC,8BAA8B,CAAC,MAAM,CAAC;QACxC,CAAC,CAAC,IAAI,CAAC;AACX,CAAC,CAAC;AAEF,MAAM,
|
|
1
|
+
{"version":3,"file":"mutable-result.mjs","sourceRoot":"","sources":["../../src/rules/mutable-result.mts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"no-unnecessary-type-guard.d.mts","sourceRoot":"","sources":["../../src/rules/no-unnecessary-type-guard.mts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,QAAQ,EAEd,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"no-unnecessary-type-guard.d.mts","sourceRoot":"","sources":["../../src/rules/no-unnecessary-type-guard.mts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,QAAQ,EAEd,MAAM,0BAA0B,CAAC;AAWlC,KAAK,OAAO,GAAG,SAAS;IACtB,QAAQ,CAAC;QACP,+DAA+D;QAC/D,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;KAC5B,CAAC,CAAC;CACJ,CAAC;AAEF,KAAK,UAAU,GAAG,YAAY,GAAG,aAAa,GAAG,kBAAkB,CAAC;AA2FpE,eAAO,MAAM,sBAAsB,EAAE,QAAQ,CAAC,UAAU,CAAC,UAAU,EAAE,OAAO,CAmNhE,CAAC"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { AST_NODE_TYPES, ESLintUtils, } from '@typescript-eslint/utils';
|
|
2
|
-
import { buildCalleeResolver,
|
|
2
|
+
import { buildCalleeResolver, getImportDeclarations, typeWrapperLayers, } from 'eslint-rule-forge';
|
|
3
3
|
import * as ts from 'typescript';
|
|
4
4
|
import { TS_DATA_FORGE_MODULE } from './constants.mjs';
|
|
5
|
+
import { tsDataForgeValueAtByName } from './import-binding.mjs';
|
|
5
6
|
|
|
6
7
|
|
|
7
8
|
|
|
@@ -101,27 +102,25 @@ export const noUnnecessaryTypeGuard = {
|
|
|
101
102
|
const ignored = new Set(options?.ignore);
|
|
102
103
|
const tsDataForgeImports = getImportDeclarations(program, TS_DATA_FORGE_MODULE);
|
|
103
104
|
const resolveGuard = buildCalleeResolver(tsDataForgeImports);
|
|
105
|
+
|
|
106
|
+
const guardAt = tsDataForgeValueAtByName(sourceCode);
|
|
104
107
|
const buildReplaceFix = (isNamespace,
|
|
105
108
|
|
|
106
|
-
propertyNode, replacement) =>
|
|
109
|
+
propertyNode, replacement) => {
|
|
107
110
|
|
|
108
111
|
|
|
109
112
|
if (isNamespace) {
|
|
110
|
-
return [fixer.replaceText(propertyNode, replacement)];
|
|
113
|
+
return (fixer) => [fixer.replaceText(propertyNode, replacement)];
|
|
111
114
|
}
|
|
112
115
|
|
|
113
116
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
replacement,
|
|
122
|
-
]),
|
|
123
|
-
fixer.replaceText(propertyNode, replacement),
|
|
124
|
-
];
|
|
117
|
+
const guard = guardAt(replacement)(propertyNode);
|
|
118
|
+
return guard === undefined
|
|
119
|
+
? null
|
|
120
|
+
: (fixer) => [
|
|
121
|
+
...guard.edits(fixer),
|
|
122
|
+
fixer.replaceText(propertyNode, guard.localName),
|
|
123
|
+
];
|
|
125
124
|
};
|
|
126
125
|
const reportConstant = (node, name, value, argument) => {
|
|
127
126
|
|
|
@@ -146,7 +145,11 @@ export const noUnnecessaryTypeGuard = {
|
|
|
146
145
|
|
|
147
146
|
node: node,
|
|
148
147
|
messageId: 'replaceTypeGuard',
|
|
149
|
-
|
|
148
|
+
|
|
149
|
+
data: {
|
|
150
|
+
from,
|
|
151
|
+
to: isNamespace ? to : (guardAt(to)(propertyNode)?.localName ?? to),
|
|
152
|
+
},
|
|
150
153
|
fix: buildReplaceFix(isNamespace, propertyNode, to),
|
|
151
154
|
});
|
|
152
155
|
};
|
|
@@ -195,79 +198,6 @@ export const noUnnecessaryTypeGuard = {
|
|
|
195
198
|
};
|
|
196
199
|
},
|
|
197
200
|
};
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
const verdictOf = (spec,
|
|
203
|
-
|
|
204
|
-
type,
|
|
205
|
-
|
|
206
|
-
checker) => {
|
|
207
|
-
const parts = collectUnionParts(type);
|
|
208
|
-
if (parts === undefined) {
|
|
209
|
-
return undefined;
|
|
210
|
-
}
|
|
211
|
-
const inputAtoms = new Set(parts.map(classifyAtom));
|
|
212
|
-
const hasMemberOutsideTarget = (atoms) => {
|
|
213
|
-
const targetSet = new Set(atoms);
|
|
214
|
-
return parts.some((p) => !targetSet.has(classifyAtom(p)));
|
|
215
|
-
};
|
|
216
|
-
switch (spec.kind) {
|
|
217
|
-
case 'excludeFrom': {
|
|
218
|
-
const removable = spec.atoms.filter((a) => inputAtoms.has(a));
|
|
219
|
-
if (removable.length === 0) {
|
|
220
|
-
|
|
221
|
-
return { kind: 'constant', value: true };
|
|
222
|
-
}
|
|
223
|
-
if (!hasMemberOutsideTarget(spec.atoms)) {
|
|
224
|
-
|
|
225
|
-
return { kind: 'constant', value: false };
|
|
226
|
-
}
|
|
227
|
-
return replacementVerdict(removable.length < spec.atoms.length
|
|
228
|
-
? spec.replacements?.[joinAtoms(removable)]
|
|
229
|
-
: undefined);
|
|
230
|
-
}
|
|
231
|
-
case 'narrowTo': {
|
|
232
|
-
const present = spec.atoms.filter((a) => inputAtoms.has(a));
|
|
233
|
-
if (present.length === 0) {
|
|
234
|
-
|
|
235
|
-
return { kind: 'constant', value: false };
|
|
236
|
-
}
|
|
237
|
-
if (!hasMemberOutsideTarget(spec.atoms)) {
|
|
238
|
-
|
|
239
|
-
return { kind: 'constant', value: true };
|
|
240
|
-
}
|
|
241
|
-
return replacementVerdict(present.length < spec.atoms.length
|
|
242
|
-
? spec.replacements?.[joinAtoms(present)]
|
|
243
|
-
: undefined);
|
|
244
|
-
}
|
|
245
|
-
case 'record':
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
return parts.every((p) => isGuaranteedRecord(p, checker))
|
|
249
|
-
? { kind: 'constant', value: true }
|
|
250
|
-
: parts.every((p) => isGuaranteedNotRecord(p, checker))
|
|
251
|
-
? { kind: 'constant', value: false }
|
|
252
|
-
: undefined;
|
|
253
|
-
case 'nonEmptyString': {
|
|
254
|
-
const nonNullishParts = parts.filter((p) => {
|
|
255
|
-
const atom = classifyAtom(p);
|
|
256
|
-
return atom !== 'undefined' && atom !== 'null';
|
|
257
|
-
});
|
|
258
|
-
if (!nonNullishParts.some(couldBeNonEmptyString)) {
|
|
259
|
-
|
|
260
|
-
return { kind: 'constant', value: false };
|
|
261
|
-
}
|
|
262
|
-
if (nonNullishParts.some((p) => !isGuaranteedNonEmptyString(p, checker))) {
|
|
263
|
-
return undefined;
|
|
264
|
-
}
|
|
265
|
-
return inputAtoms.has('undefined') || inputAtoms.has('null')
|
|
266
|
-
? { kind: 'replace', replacement: 'isNonNullish' }
|
|
267
|
-
: { kind: 'constant', value: true };
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
};
|
|
271
201
|
const replacementVerdict = (replacement) => replacement === undefined
|
|
272
202
|
? undefined
|
|
273
203
|
: { kind: 'replace', replacement };
|
|
@@ -277,33 +207,6 @@ const replacementVerdict = (replacement) => replacement === undefined
|
|
|
277
207
|
|
|
278
208
|
|
|
279
209
|
|
|
280
|
-
|
|
281
|
-
const holdsOn = (verdict, spec,
|
|
282
|
-
|
|
283
|
-
type,
|
|
284
|
-
|
|
285
|
-
checker) => {
|
|
286
|
-
const onType = verdictOf(spec, type, checker);
|
|
287
|
-
if (verdict.kind === 'constant') {
|
|
288
|
-
return onType?.kind === 'constant' && onType.value === verdict.value;
|
|
289
|
-
}
|
|
290
|
-
if (onType?.kind === 'replace') {
|
|
291
|
-
return onType.replacement === verdict.replacement;
|
|
292
|
-
}
|
|
293
|
-
const replacementSpec = GUARD_SPECS[verdict.replacement];
|
|
294
|
-
const replacementOnType = replacementSpec === undefined
|
|
295
|
-
? undefined
|
|
296
|
-
: verdictOf(replacementSpec, type, checker);
|
|
297
|
-
return (onType?.kind === 'constant' &&
|
|
298
|
-
replacementOnType?.kind === 'constant' &&
|
|
299
|
-
replacementOnType.value === onType.value);
|
|
300
|
-
};
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
210
|
const collectUnionParts = (type) => {
|
|
308
211
|
const parts = type.isUnion() ? type.types : [type];
|
|
309
212
|
for (const part of parts) {
|
|
@@ -313,6 +216,12 @@ const collectUnionParts = (type) => {
|
|
|
313
216
|
}
|
|
314
217
|
return parts;
|
|
315
218
|
};
|
|
219
|
+
const isCallableType = (
|
|
220
|
+
|
|
221
|
+
type,
|
|
222
|
+
|
|
223
|
+
checker) => checker.getSignaturesOfType(type, ts.SignatureKind.Call).length > 0 ||
|
|
224
|
+
checker.getSignaturesOfType(type, ts.SignatureKind.Construct).length > 0;
|
|
316
225
|
|
|
317
226
|
|
|
318
227
|
|
|
@@ -336,25 +245,6 @@ checker) => checker.getIndexInfoOfType(type, ts.IndexKind.String) !== undefined
|
|
|
336
245
|
!checker.isTupleType(type);
|
|
337
246
|
|
|
338
247
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
const isGuaranteedNotRecord = (
|
|
343
|
-
|
|
344
|
-
type,
|
|
345
|
-
|
|
346
|
-
checker) => classifyAtom(type) !== 'other' ||
|
|
347
|
-
checker.isArrayType(type) ||
|
|
348
|
-
checker.isTupleType(type) ||
|
|
349
|
-
isCallableType(type, checker);
|
|
350
|
-
const isCallableType = (
|
|
351
|
-
|
|
352
|
-
type,
|
|
353
|
-
|
|
354
|
-
checker) => checker.getSignaturesOfType(type, ts.SignatureKind.Call).length > 0 ||
|
|
355
|
-
checker.getSignaturesOfType(type, ts.SignatureKind.Construct).length > 0;
|
|
356
|
-
|
|
357
|
-
|
|
358
248
|
const classifyAtom = (type) => {
|
|
359
249
|
const { flags } = type;
|
|
360
250
|
if ((flags & ts.TypeFlags.Undefined) !== 0) {
|
|
@@ -390,15 +280,19 @@ const classifyAtom = (type) => {
|
|
|
390
280
|
}
|
|
391
281
|
return 'other';
|
|
392
282
|
};
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
const isGuaranteedNotRecord = (
|
|
289
|
+
|
|
290
|
+
type,
|
|
291
|
+
|
|
292
|
+
checker) => classifyAtom(type) !== 'other' ||
|
|
293
|
+
checker.isArrayType(type) ||
|
|
294
|
+
checker.isTupleType(type) ||
|
|
295
|
+
isCallableType(type, checker);
|
|
402
296
|
|
|
403
297
|
const joinAtoms = (atoms) => ATOM_ORDER.filter((atom) => atoms.includes(atom)).join('|');
|
|
404
298
|
|
|
@@ -437,6 +331,115 @@ const couldBeNonEmptyString = (type) => type.isStringLiteral() ? type.value !==
|
|
|
437
331
|
|
|
438
332
|
|
|
439
333
|
|
|
334
|
+
const verdictOf = (spec,
|
|
335
|
+
|
|
336
|
+
type,
|
|
337
|
+
|
|
338
|
+
checker) => {
|
|
339
|
+
const parts = collectUnionParts(type);
|
|
340
|
+
if (parts === undefined) {
|
|
341
|
+
return undefined;
|
|
342
|
+
}
|
|
343
|
+
const inputAtoms = new Set(parts.map(classifyAtom));
|
|
344
|
+
const hasMemberOutsideTarget = (atoms) => {
|
|
345
|
+
const targetSet = new Set(atoms);
|
|
346
|
+
return parts.some((p) => !targetSet.has(classifyAtom(p)));
|
|
347
|
+
};
|
|
348
|
+
switch (spec.kind) {
|
|
349
|
+
case 'excludeFrom': {
|
|
350
|
+
const removable = spec.atoms.filter((a) => inputAtoms.has(a));
|
|
351
|
+
if (removable.length === 0) {
|
|
352
|
+
|
|
353
|
+
return { kind: 'constant', value: true };
|
|
354
|
+
}
|
|
355
|
+
if (!hasMemberOutsideTarget(spec.atoms)) {
|
|
356
|
+
|
|
357
|
+
return { kind: 'constant', value: false };
|
|
358
|
+
}
|
|
359
|
+
return replacementVerdict(removable.length < spec.atoms.length
|
|
360
|
+
? spec.replacements?.[joinAtoms(removable)]
|
|
361
|
+
: undefined);
|
|
362
|
+
}
|
|
363
|
+
case 'narrowTo': {
|
|
364
|
+
const present = spec.atoms.filter((a) => inputAtoms.has(a));
|
|
365
|
+
if (present.length === 0) {
|
|
366
|
+
|
|
367
|
+
return { kind: 'constant', value: false };
|
|
368
|
+
}
|
|
369
|
+
if (!hasMemberOutsideTarget(spec.atoms)) {
|
|
370
|
+
|
|
371
|
+
return { kind: 'constant', value: true };
|
|
372
|
+
}
|
|
373
|
+
return replacementVerdict(present.length < spec.atoms.length
|
|
374
|
+
? spec.replacements?.[joinAtoms(present)]
|
|
375
|
+
: undefined);
|
|
376
|
+
}
|
|
377
|
+
case 'record':
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
return parts.every((p) => isGuaranteedRecord(p, checker))
|
|
381
|
+
? { kind: 'constant', value: true }
|
|
382
|
+
: parts.every((p) => isGuaranteedNotRecord(p, checker))
|
|
383
|
+
? { kind: 'constant', value: false }
|
|
384
|
+
: undefined;
|
|
385
|
+
case 'nonEmptyString': {
|
|
386
|
+
const nonNullishParts = parts.filter((p) => {
|
|
387
|
+
const atom = classifyAtom(p);
|
|
388
|
+
return atom !== 'undefined' && atom !== 'null';
|
|
389
|
+
});
|
|
390
|
+
if (!nonNullishParts.some(couldBeNonEmptyString)) {
|
|
391
|
+
|
|
392
|
+
return { kind: 'constant', value: false };
|
|
393
|
+
}
|
|
394
|
+
if (nonNullishParts.some((p) => !isGuaranteedNonEmptyString(p, checker))) {
|
|
395
|
+
return undefined;
|
|
396
|
+
}
|
|
397
|
+
return inputAtoms.has('undefined') || inputAtoms.has('null')
|
|
398
|
+
? { kind: 'replace', replacement: 'isNonNullish' }
|
|
399
|
+
: { kind: 'constant', value: true };
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
};
|
|
403
|
+
|
|
404
|
+
|
|
405
|
+
|
|
406
|
+
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
|
|
410
|
+
const holdsOn = (verdict, spec,
|
|
411
|
+
|
|
412
|
+
type,
|
|
413
|
+
|
|
414
|
+
checker) => {
|
|
415
|
+
const onType = verdictOf(spec, type, checker);
|
|
416
|
+
if (verdict.kind === 'constant') {
|
|
417
|
+
return onType?.kind === 'constant' && onType.value === verdict.value;
|
|
418
|
+
}
|
|
419
|
+
if (onType?.kind === 'replace') {
|
|
420
|
+
return onType.replacement === verdict.replacement;
|
|
421
|
+
}
|
|
422
|
+
const replacementSpec = GUARD_SPECS[verdict.replacement];
|
|
423
|
+
const replacementOnType = replacementSpec === undefined
|
|
424
|
+
? undefined
|
|
425
|
+
: verdictOf(replacementSpec, type, checker);
|
|
426
|
+
return (onType?.kind === 'constant' &&
|
|
427
|
+
replacementOnType?.kind === 'constant' &&
|
|
428
|
+
replacementOnType.value === onType.value);
|
|
429
|
+
};
|
|
430
|
+
const ATOM_ORDER = [
|
|
431
|
+
'undefined',
|
|
432
|
+
'null',
|
|
433
|
+
'boolean',
|
|
434
|
+
'number',
|
|
435
|
+
'string',
|
|
436
|
+
'bigint',
|
|
437
|
+
'symbol',
|
|
438
|
+
];
|
|
439
|
+
|
|
440
|
+
|
|
441
|
+
|
|
442
|
+
|
|
440
443
|
|
|
441
444
|
const isSideEffectFreeArg = (node) => {
|
|
442
445
|
|