eslint-plugin-ts-data-forge 0.8.6 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -19
- package/dist/plugin.d.mts +2 -0
- package/dist/plugin.d.mts.map +1 -1
- package/dist/plugin.mjs +1 -0
- package/dist/plugin.mjs.map +1 -1
- package/dist/rule-types.d.mts +16 -1
- package/dist/rule-types.d.mts.map +1 -1
- package/dist/rule-types.mjs.map +1 -1
- package/dist/rules/ast-utils.d.mts +21 -2
- package/dist/rules/ast-utils.d.mts.map +1 -1
- package/dist/rules/ast-utils.mjs +51 -4
- package/dist/rules/ast-utils.mjs.map +1 -1
- package/dist/rules/constants.d.mts +2 -0
- package/dist/rules/constants.d.mts.map +1 -1
- package/dist/rules/constants.mjs +9 -0
- package/dist/rules/constants.mjs.map +1 -1
- package/dist/rules/mutable-result.d.mts +10 -0
- package/dist/rules/mutable-result.d.mts.map +1 -0
- package/dist/rules/mutable-result.mjs +145 -0
- package/dist/rules/mutable-result.mjs.map +1 -0
- package/dist/rules/prefer-arr-generate.d.mts +57 -0
- package/dist/rules/prefer-arr-generate.d.mts.map +1 -0
- package/dist/rules/prefer-arr-generate.mjs +588 -0
- package/dist/rules/prefer-arr-generate.mjs.map +1 -0
- package/dist/rules/prefer-arr-uniq.d.mts.map +1 -1
- package/dist/rules/prefer-arr-uniq.mjs +2 -149
- package/dist/rules/prefer-arr-uniq.mjs.map +1 -1
- package/dist/rules/prefer-canonical-array-slicing.d.mts.map +1 -1
- package/dist/rules/prefer-canonical-array-slicing.mjs +47 -28
- package/dist/rules/prefer-canonical-array-slicing.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 +110 -40
- 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 +102 -45
- package/dist/rules/prefer-is-record-and-has-key.mjs.map +1 -1
- package/dist/rules/prefer-range-for-loop.d.mts.map +1 -1
- package/dist/rules/prefer-range-for-loop.mjs +97 -16
- package/dist/rules/prefer-range-for-loop.mjs.map +1 -1
- package/dist/rules/rules.d.mts +1 -0
- package/dist/rules/rules.d.mts.map +1 -1
- package/dist/rules/rules.mjs +2 -0
- package/dist/rules/rules.mjs.map +1 -1
- package/package.json +11 -11
- package/src/plugin.mts +1 -0
- package/src/rule-types.mts +17 -1
- package/src/rules/ast-utils.mts +72 -5
- package/src/rules/constants.mts +12 -0
- package/src/rules/mutable-result.mts +204 -0
- package/src/rules/prefer-arr-generate.mts +918 -0
- package/src/rules/prefer-arr-generate.test.mts +967 -0
- package/src/rules/prefer-arr-is-bounded-length-array.test.mts +19 -0
- package/src/rules/prefer-arr-is-max-length-array.test.mts +8 -0
- package/src/rules/prefer-arr-is-min-length-array.test.mts +8 -0
- package/src/rules/prefer-arr-uniq.mts +2 -207
- package/src/rules/prefer-canonical-array-slicing.mts +57 -40
- package/src/rules/prefer-canonical-array-slicing.test.mts +55 -0
- package/src/rules/prefer-is-non-null-object.mts +160 -57
- package/src/rules/prefer-is-non-null-object.test.mts +138 -0
- package/src/rules/prefer-is-record-and-has-key.mts +148 -67
- package/src/rules/prefer-is-record-and-has-key.test.mts +118 -23
- package/src/rules/prefer-range-for-loop.mts +142 -21
- package/src/rules/prefer-range-for-loop.test.mts +127 -5
- package/src/rules/rules.mts +2 -0
package/README.md
CHANGED
|
@@ -66,25 +66,26 @@ export default [
|
|
|
66
66
|
|
|
67
67
|
## Rules
|
|
68
68
|
|
|
69
|
-
| Rule | Description
|
|
70
|
-
| -------------------------------------- |
|
|
71
|
-
| `prefer-canonical-array-slicing` | Unify non-mutating array add/remove patterns into `Arr.tail`/`skip`/`take`/etc.
|
|
72
|
-
| `prefer-canonical-length-guard` | Normalize array-length checks to the canonical `Arr` guard (`xs.length > 0` → `Arr.isNonEmpty`, `Arr.isFixedLengthArray(0, xs)` → `Arr.isEmpty`, `Arr.isFixedLengthTuple(0, xs)` → `Arr.isEmptyTuple`, …).
|
|
73
|
-
| `prefer-canonical-length-cast` | Normalize a degenerate `Arr` length cast to the canonical one (`Arr.asMinLengthArray(1, xs)` → `Arr.asNonEmptyArray(xs)`, `Arr.asBoundedLengthArray(n, n, xs)` → `Arr.asFixedLengthArray(n, xs)`, …).
|
|
74
|
-
| `prefer-arr-
|
|
75
|
-
| `prefer-arr-
|
|
76
|
-
| `prefer-arr-
|
|
77
|
-
| `prefer-arr-
|
|
78
|
-
| `prefer-
|
|
79
|
-
| `prefer-
|
|
80
|
-
| `prefer-
|
|
81
|
-
| `prefer-
|
|
82
|
-
| `prefer-
|
|
83
|
-
| `prefer-num-safe-parse-
|
|
84
|
-
| `
|
|
85
|
-
| `
|
|
86
|
-
| `prefer-
|
|
87
|
-
| `
|
|
69
|
+
| Rule | Description |
|
|
70
|
+
| -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
71
|
+
| `prefer-canonical-array-slicing` | Unify non-mutating array add/remove patterns into `Arr.tail`/`skip`/`take`/etc. |
|
|
72
|
+
| `prefer-canonical-length-guard` | Normalize array-length checks to the canonical `Arr` guard (`xs.length > 0` → `Arr.isNonEmpty`, `Arr.isFixedLengthArray(0, xs)` → `Arr.isEmpty`, `Arr.isFixedLengthTuple(0, xs)` → `Arr.isEmptyTuple`, …). |
|
|
73
|
+
| `prefer-canonical-length-cast` | Normalize a degenerate `Arr` length cast to the canonical one (`Arr.asMinLengthArray(1, xs)` → `Arr.asNonEmptyArray(xs)`, `Arr.asBoundedLengthArray(n, n, xs)` → `Arr.asFixedLengthArray(n, xs)`, …). |
|
|
74
|
+
| `prefer-arr-generate` | Replace the filter-and-map idiom `xs.flatMap((x) => (cond ? [f(x)] : []))` with a `for…of` loop in `Arr.generate` (type-aware). Suggests instead of fixing when the result is used as a mutable array, when a type annotation, a type wrapper or a comment would be dropped, when the receiver relies on a narrowing the generator function would not see, or when it is a `filter()` call. |
|
|
75
|
+
| `prefer-arr-is-array` | Replace `Array.isArray` with `Arr.isArray`. |
|
|
76
|
+
| `prefer-arr-scan` | Report an accumulated value rebuilt for every element (`xs.map((_, i) => f(...xs.slice(0, i + 1)))`, or a `reduce` that appends to its accumulator) and point at `Arr.scan`. Fixes the `reduce` form. |
|
|
77
|
+
| `prefer-arr-sum` | Replace `xs.reduce((a, b) => a + b, 0)` with `Arr.sum(xs)` / `Arr.sumBy(xs, fn)`. |
|
|
78
|
+
| `prefer-arr-uniq` | Replace `Array.from(new Set(xs))` / `[...new Set(xs)]` with `Arr.uniq(xs)` when `xs` is an array of primitives (type-aware). Suggests instead of fixing when the result is used as a mutable array. |
|
|
79
|
+
| `prefer-as-int` | Replace branded-number assertions (`x as Int`) with `asInt(x)`-style casts. |
|
|
80
|
+
| `prefer-is-non-null-object` | Replace `typeof u === 'object' && u !== null` with `isNonNullObject(u)`. |
|
|
81
|
+
| `prefer-range-for-loop` | Replace C-style `for` loops with `for (const i of range(begin, end))`. |
|
|
82
|
+
| `prefer-is-record-and-has-key` | Replace `Object.hasOwn(obj, key)` / `key in obj` with `isRecord(obj) && hasKey(…)`. |
|
|
83
|
+
| `prefer-num-safe-parse-int` | Replace `parseInt(x, 10)` with `Result.unwrapOkOr(Num.safeParseInt(x), NaN)`. |
|
|
84
|
+
| `prefer-num-safe-parse-float` | Replace `parseFloat(x)` / `Number(x)` with `Num.safeParseFloat`-based parsing. |
|
|
85
|
+
| `no-unnecessary-type-guard` | Flag `ts-data-forge` type-guard calls that do no narrowing (type-aware). |
|
|
86
|
+
| `prefer-comparison-over-nullish-guard` | Prefer direct `=== null` / `!== undefined` over `isNull` / `isNotUndefined` calls. |
|
|
87
|
+
| `prefer-obj-over-entries-round-trip` | Replace an `Object.fromEntries(Object.entries(o).map/filter/flatMap(…))` round trip with `Obj.map` / `Obj.filter` / `Obj.filterMap`. |
|
|
88
|
+
| `no-side-effect-import` | Remove a side-effect-only `import 'ts-data-forge';`; the package declares `sideEffects: false`, so it binds no name and does nothing. |
|
|
88
89
|
|
|
89
90
|
## License
|
|
90
91
|
|
package/dist/plugin.d.mts
CHANGED
|
@@ -7,6 +7,7 @@ export declare const eslintPluginTsDataForge: {
|
|
|
7
7
|
readonly 'prefer-canonical-array-slicing': import("@typescript-eslint/utils/ts-eslint").RuleModule<"preferCanonicalArraySlicing", readonly [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
8
8
|
readonly 'prefer-canonical-length-guard': import("@typescript-eslint/utils/ts-eslint").RuleModule<"useCanonicalGuard" | "useIsBoundedLengthArray" | "useIsFixedLengthArray" | "useIsMaxLengthArray" | "useIsMinLengthArray" | "useIsNonEmpty", readonly [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
9
9
|
readonly 'prefer-canonical-length-cast': import("@typescript-eslint/utils/ts-eslint").RuleModule<"useCanonicalCast", readonly [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
10
|
+
readonly 'prefer-arr-generate': import("@typescript-eslint/utils/ts-eslint").RuleModule<"suggestArrGenerate" | "useArrGenerate", readonly [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
10
11
|
readonly 'prefer-arr-is-array': import("@typescript-eslint/utils/ts-eslint").RuleModule<"useArrIsArray", readonly [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
11
12
|
readonly 'prefer-arr-scan': import("@typescript-eslint/utils/ts-eslint").RuleModule<"preferArrScanAccumulate" | "preferArrScanPrefix", readonly [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
12
13
|
readonly 'prefer-arr-sum': import("@typescript-eslint/utils/ts-eslint").RuleModule<"useArrSum" | "useArrSumBy", readonly [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
@@ -35,6 +36,7 @@ export declare const eslintPluginTsDataForge: {
|
|
|
35
36
|
readonly 'ts-data-forge/prefer-canonical-array-slicing': 'error';
|
|
36
37
|
readonly 'ts-data-forge/prefer-canonical-length-cast': 'error';
|
|
37
38
|
readonly 'ts-data-forge/prefer-canonical-length-guard': 'error';
|
|
39
|
+
readonly 'ts-data-forge/prefer-arr-generate': 'error';
|
|
38
40
|
readonly 'ts-data-forge/prefer-arr-is-array': 'error';
|
|
39
41
|
readonly 'ts-data-forge/prefer-arr-scan': 'error';
|
|
40
42
|
readonly 'ts-data-forge/prefer-arr-sum': 'error';
|
package/dist/plugin.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.mts","sourceRoot":"","sources":["../src/plugin.mts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAoB,YAAY,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"plugin.d.mts","sourceRoot":"","sources":["../src/plugin.mts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAoB,YAAY,EAAE,MAAM,aAAa,CAAC;AAiDlE,eAAO,MAAM,uBAAuB;;iBAEhC,IAAI,EAAE,6BAA6B;;;;;;;;;;;;;;;;;;;;;;;;;QAInC,oDAAoD;iBACpD,WAAW;2BAtBP,2BAA2B;;yBAQ3B,eAAe,EAAI,YAAY;;;yEAhCW,OAAO;uEACT,OAAO;wEACN,OAAO;8DACjB,OAAO;8DACP,OAAO;0DACX,OAAO;yDACR,OAAO;0DACN,OAAO;wDACT,OAAO;oEACK,OAAO;gEACX,OAAO;uEACA,OAAO;oEACV,OAAO;sEACL,OAAO;gEACb,OAAO;oEACH,OAAO;+EACI,OAAO;6EACT,OAAO;;;;CA+B5B,CAAC"}
|
package/dist/plugin.mjs
CHANGED
|
@@ -10,6 +10,7 @@ const recommendedRules = {
|
|
|
10
10
|
'ts-data-forge/prefer-canonical-array-slicing': 'error',
|
|
11
11
|
'ts-data-forge/prefer-canonical-length-cast': 'error',
|
|
12
12
|
'ts-data-forge/prefer-canonical-length-guard': 'error',
|
|
13
|
+
'ts-data-forge/prefer-arr-generate': 'error',
|
|
13
14
|
'ts-data-forge/prefer-arr-is-array': 'error',
|
|
14
15
|
'ts-data-forge/prefer-arr-scan': 'error',
|
|
15
16
|
'ts-data-forge/prefer-arr-sum': 'error',
|
package/dist/plugin.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.mjs","sourceRoot":"","sources":["../src/plugin.mts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAGrD;;;;;;GAMG;AACH,MAAM,gBAAgB,GAAG;IACvB,8CAA8C,EAAE,OAAO;IACvD,4CAA4C,EAAE,OAAO;IACrD,6CAA6C,EAAE,OAAO;IACtD,mCAAmC,EAAE,OAAO;IAC5C,+BAA+B,EAAE,OAAO;IACxC,8BAA8B,EAAE,OAAO;IACvC,+BAA+B,EAAE,OAAO;IACxC,6BAA6B,EAAE,OAAO;IACtC,yCAAyC,EAAE,OAAO;IAClD,qCAAqC,EAAE,OAAO;IAC9C,4CAA4C,EAAE,OAAO;IACrD,yCAAyC,EAAE,OAAO;IAClD,2CAA2C,EAAE,OAAO;IACpD,qCAAqC,EAAE,OAAO;IAC9C,yCAAyC,EAAE,OAAO;IAClD,oDAAoD,EAAE,OAAO;IAC7D,kDAAkD,EAAE,OAAO;CAI5D,CAAC;AAEF,MAAM,iBAAiB,GAAG;IACxB,IAAI,EAAE,2BAA2B;IACjC,OAAO,EAAE;QACP,uEAAuE;QACvE,yEAAyE;QACzE,wEAAwE;QACxE,mDAAmD;QACnD,0EAA0E;QAC1E,wDAAwD;QACxD,IAAI,eAAe;YACjB,OAAO,uBAAuB,CAAC;QACjC,CAAC;KACF;IACD,KAAK,EAAE,gBAAgB;CACY,CAAC;AAEtC,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,IAAI,EAAE;QACJ,IAAI,EAAE,6BAA6B;KACpC;IACD,KAAK,EAAE,gBAAgB;IACvB,OAAO,EAAE;QACP,oDAAoD;QACpD,WAAW,EAAE,iBAAiB;KAC/B;CAC8B,CAAC"}
|
|
1
|
+
{"version":3,"file":"plugin.mjs","sourceRoot":"","sources":["../src/plugin.mts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAGrD;;;;;;GAMG;AACH,MAAM,gBAAgB,GAAG;IACvB,8CAA8C,EAAE,OAAO;IACvD,4CAA4C,EAAE,OAAO;IACrD,6CAA6C,EAAE,OAAO;IACtD,mCAAmC,EAAE,OAAO;IAC5C,mCAAmC,EAAE,OAAO;IAC5C,+BAA+B,EAAE,OAAO;IACxC,8BAA8B,EAAE,OAAO;IACvC,+BAA+B,EAAE,OAAO;IACxC,6BAA6B,EAAE,OAAO;IACtC,yCAAyC,EAAE,OAAO;IAClD,qCAAqC,EAAE,OAAO;IAC9C,4CAA4C,EAAE,OAAO;IACrD,yCAAyC,EAAE,OAAO;IAClD,2CAA2C,EAAE,OAAO;IACpD,qCAAqC,EAAE,OAAO;IAC9C,yCAAyC,EAAE,OAAO;IAClD,oDAAoD,EAAE,OAAO;IAC7D,kDAAkD,EAAE,OAAO;CAI5D,CAAC;AAEF,MAAM,iBAAiB,GAAG;IACxB,IAAI,EAAE,2BAA2B;IACjC,OAAO,EAAE;QACP,uEAAuE;QACvE,yEAAyE;QACzE,wEAAwE;QACxE,mDAAmD;QACnD,0EAA0E;QAC1E,wDAAwD;QACxD,IAAI,eAAe;YACjB,OAAO,uBAAuB,CAAC;QACjC,CAAC;KACF;IACD,KAAK,EAAE,gBAAgB;CACY,CAAC;AAEtC,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,IAAI,EAAE;QACJ,IAAI,EAAE,6BAA6B;KACpC;IACD,KAAK,EAAE,gBAAgB;IACvB,OAAO,EAAE;QACP,oDAAoD;QACpD,WAAW,EAAE,iBAAiB;KAC/B;CAC8B,CAAC"}
|
package/dist/rule-types.d.mts
CHANGED
|
@@ -50,6 +50,20 @@ declare namespace PreferCanonicalLengthGuard {
|
|
|
50
50
|
declare namespace PreferCanonicalLengthCast {
|
|
51
51
|
type RuleEntry = Linter.StringSeverity;
|
|
52
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* @description Replace the filter-and-map idiom `xs.flatMap((x) => (cond ? [f(x)] : []))` with a loop in `Arr.generate` from ts-data-forge.
|
|
55
|
+
*
|
|
56
|
+
* ```md
|
|
57
|
+
* | key | value |
|
|
58
|
+
* | :--------- | :--------- |
|
|
59
|
+
* | type | suggestion |
|
|
60
|
+
* | deprecated | false |
|
|
61
|
+
* | fixable | code |
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
declare namespace PreferArrGenerate {
|
|
65
|
+
type RuleEntry = Linter.StringSeverity;
|
|
66
|
+
}
|
|
53
67
|
/**
|
|
54
68
|
* @description Replace `Array.isArray` with `Arr.isArray` from ts-data-forge.
|
|
55
69
|
*
|
|
@@ -121,7 +135,7 @@ declare namespace PreferAsInt {
|
|
|
121
135
|
type RuleEntry = Linter.StringSeverity;
|
|
122
136
|
}
|
|
123
137
|
/**
|
|
124
|
-
* @description Replace `typeof u === "object" && u !== null
|
|
138
|
+
* @description Replace `typeof u === "object" && u !== null`, in either order and anywhere in an `&&` chain, with `isNonNullObject(u)` from ts-data-forge.
|
|
125
139
|
*
|
|
126
140
|
* ```md
|
|
127
141
|
* | key | value |
|
|
@@ -272,6 +286,7 @@ export type EslintTsDataForgeRules = Readonly<{
|
|
|
272
286
|
'ts-data-forge/prefer-canonical-array-slicing': PreferCanonicalArraySlicing.RuleEntry;
|
|
273
287
|
'ts-data-forge/prefer-canonical-length-guard': PreferCanonicalLengthGuard.RuleEntry;
|
|
274
288
|
'ts-data-forge/prefer-canonical-length-cast': PreferCanonicalLengthCast.RuleEntry;
|
|
289
|
+
'ts-data-forge/prefer-arr-generate': PreferArrGenerate.RuleEntry;
|
|
275
290
|
'ts-data-forge/prefer-arr-is-array': PreferArrIsArray.RuleEntry;
|
|
276
291
|
'ts-data-forge/prefer-arr-scan': PreferArrScan.RuleEntry;
|
|
277
292
|
'ts-data-forge/prefer-arr-sum': PreferArrSum.RuleEntry;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rule-types.d.mts","sourceRoot":"","sources":["../src/rule-types.mts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"rule-types.d.mts","sourceRoot":"","sources":["../src/rule-types.mts"],"names":[],"mappings":"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"}
|
package/dist/rule-types.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rule-types.mjs","sourceRoot":"","sources":["../src/rule-types.mts"],"names":[],"mappings":"AAAA,oBAAoB;AAOpB,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"rule-types.mjs","sourceRoot":"","sources":["../src/rule-types.mts"],"names":[],"mappings":"AAAA,oBAAoB;AAOpB,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAyV3C,8EAA8E;AAC9E,8DAA8D;AAC9D,UAAU,CAGR,GAAG,CAAC,CAAC"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type TSESLint, type TSESTree } from '@typescript-eslint/utils';
|
|
2
2
|
import type { DeepReadonly } from 'ts-type-forge';
|
|
3
|
+
import type * as ts from 'typescript';
|
|
3
4
|
/**
|
|
4
5
|
* Whether `node` is an array or a tuple at every layer of type wrappers (see
|
|
5
6
|
* {@link typeWrapperLayers}): a cast does not make a string an array, and the
|
|
@@ -33,21 +34,39 @@ type LengthComparison = Readonly<{
|
|
|
33
34
|
* Parses a `<array>.length <op> <bound>` comparison (in either operand order)
|
|
34
35
|
* into its array expression, integer-literal/`const` `bound`, and whether it is
|
|
35
36
|
* a lower (`min`) or upper (`max`) length bound. Returns `undefined` for
|
|
36
|
-
* anything else. The length and the bound are read through
|
|
37
|
+
* anything else. The comparison, the length and the bound are read through
|
|
38
|
+
* type wrappers; the
|
|
37
39
|
* `bound` returned is the literal or constant underneath, since a wrapper such
|
|
38
40
|
* as `as number` would only widen the length a guard narrows to.
|
|
39
41
|
*
|
|
40
42
|
* - `xs.length >= n` / `n <= xs.length` → `min`
|
|
41
43
|
* - `xs.length <= n` / `n >= xs.length` → `max`
|
|
42
44
|
*/
|
|
43
|
-
export declare const parseLengthComparison: (
|
|
45
|
+
export declare const parseLengthComparison: (wrapped: TSESTree.Expression, sourceCode: TSESLint.SourceCode) => LengthComparison | undefined;
|
|
44
46
|
/**
|
|
45
47
|
* `true` when `node` is one operand of an `a && b` whose other operand is the
|
|
46
48
|
* complementary length bound (`min` vs `max`) on the same array — i.e. the two
|
|
47
49
|
* together form the `Arr.isBoundedLengthArray` pattern handled by
|
|
48
50
|
* `prefer-arr-is-bounded-length-array`. The single-bound rules skip such
|
|
49
51
|
* operands so the bounded rule rewrites the whole `&&` instead of the parts.
|
|
52
|
+
* A comparison wrapped as a whole (`(xs.length >= 1 satisfies boolean) && …`)
|
|
53
|
+
* is still the operand.
|
|
50
54
|
*/
|
|
51
55
|
export declare const isPartOfBoundedLengthCheck: (node: TSESTree.BinaryExpression, sourceCode: TSESLint.SourceCode) => boolean;
|
|
56
|
+
/**
|
|
57
|
+
* Whether `node`, read through its type wrappers, is the identifier `name`:
|
|
58
|
+
* `Number`, `(Number as NumberConstructor)` and `Number!` are the same object.
|
|
59
|
+
*/
|
|
60
|
+
export declare const isIdentifierNamed: (node: TSESTree.Node, name: string) => boolean;
|
|
61
|
+
/**
|
|
62
|
+
* Whether `holds` is true of the type of every layer of type wrappers around
|
|
63
|
+
* `node` (see {@link typeWrapperLayers}), outermost to innermost; `false`
|
|
64
|
+
* without type information. A widening cast (`s as string | number`) is the
|
|
65
|
+
* author saying the value may be more than it is, and is respected; a
|
|
66
|
+
* narrowing one (`s!`, `v as unknown as string`) cannot vouch for what the
|
|
67
|
+
* value's own type does not, and the fix, which keeps the wrapper, has to
|
|
68
|
+
* type-check at every layer too.
|
|
69
|
+
*/
|
|
70
|
+
export declare const typeHoldsAtEveryLayer: (sourceCode: TSESLint.SourceCode, node: TSESTree.Node, holds: (type: ts.Type, typeChecker: ts.TypeChecker) => boolean) => boolean;
|
|
52
71
|
export {};
|
|
53
72
|
//# 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;AAClD,OAAO,KAAK,KAAK,EAAE,MAAM,YAAY,CAAC;AAOtC;;;;;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,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;AAEH;;;;;;;;;;;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;AAuBF;;;GAGG;AACH,eAAO,MAAM,iBAAiB,SAEtB,QAAQ,CAAC,IAAI,QACb,MAAM,KACX,OAMF,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,qBAAqB,eAEpB,QAAQ,CAAC,UAAU,QAEzB,QAAQ,CAAC,IAAI,SAEZ,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,WAAW,EAAE,EAAE,CAAC,WAAW,KAAK,OAAO,KAC7D,OAgBF,CAAC"}
|
package/dist/rules/ast-utils.mjs
CHANGED
|
@@ -106,11 +106,13 @@ sourceCode) => sourceCode.getText(skipTypeWrappers(a)) ===
|
|
|
106
106
|
|
|
107
107
|
|
|
108
108
|
|
|
109
|
+
|
|
109
110
|
export const parseLengthComparison = (
|
|
110
111
|
|
|
111
|
-
|
|
112
|
+
wrapped,
|
|
112
113
|
|
|
113
114
|
sourceCode) => {
|
|
115
|
+
const node = skipTypeWrappers(wrapped);
|
|
114
116
|
if (node.type !== AST_NODE_TYPES.BinaryExpression ||
|
|
115
117
|
(node.operator !== '>=' && node.operator !== '<=')) {
|
|
116
118
|
return undefined;
|
|
@@ -142,13 +144,16 @@ sourceCode) => {
|
|
|
142
144
|
|
|
143
145
|
|
|
144
146
|
|
|
147
|
+
|
|
148
|
+
|
|
145
149
|
export const isPartOfBoundedLengthCheck = (
|
|
146
150
|
|
|
147
151
|
node,
|
|
148
152
|
|
|
149
153
|
sourceCode) => {
|
|
150
|
-
const
|
|
151
|
-
|
|
154
|
+
const operand = outermostTypeWrapper(node);
|
|
155
|
+
const { parent } = operand;
|
|
156
|
+
if (parent?.type !== AST_NODE_TYPES.LogicalExpression ||
|
|
152
157
|
parent.operator !== '&&') {
|
|
153
158
|
return false;
|
|
154
159
|
}
|
|
@@ -156,7 +161,7 @@ sourceCode) => {
|
|
|
156
161
|
if (self === undefined) {
|
|
157
162
|
return false;
|
|
158
163
|
}
|
|
159
|
-
const sibling = parent.left ===
|
|
164
|
+
const sibling = parent.left === operand ? parent.right : parent.left;
|
|
160
165
|
const other = parseLengthComparison(sibling, sourceCode);
|
|
161
166
|
if (other === undefined) {
|
|
162
167
|
return false;
|
|
@@ -164,7 +169,49 @@ sourceCode) => {
|
|
|
164
169
|
return (self.kind !== other.kind &&
|
|
165
170
|
isSameArrayText(self.array, other.array, sourceCode));
|
|
166
171
|
};
|
|
172
|
+
|
|
173
|
+
const outermostTypeWrapper = (
|
|
174
|
+
|
|
175
|
+
node) => node.parent !== undefined && isTypeWrapper(node.parent)
|
|
176
|
+
? outermostTypeWrapper(node.parent)
|
|
177
|
+
: node;
|
|
167
178
|
const isVariableDefinition = (
|
|
168
179
|
|
|
169
180
|
def) => def.type === 'Variable';
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
export const isIdentifierNamed = (
|
|
186
|
+
|
|
187
|
+
node, name) => {
|
|
188
|
+
const unwrapped = skipTypeWrappers(node);
|
|
189
|
+
return (unwrapped.type === AST_NODE_TYPES.Identifier && unwrapped.name === name);
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
export const typeHoldsAtEveryLayer = (
|
|
201
|
+
|
|
202
|
+
sourceCode,
|
|
203
|
+
|
|
204
|
+
node,
|
|
205
|
+
|
|
206
|
+
holds) => {
|
|
207
|
+
const services = sourceCode.parserServices;
|
|
208
|
+
const checker = services?.program?.getTypeChecker();
|
|
209
|
+
if (checker === undefined) {
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
212
|
+
return typeWrapperLayers(node).every((layer) => {
|
|
213
|
+
const tsNode = services?.esTreeNodeToTSNodeMap?.get(layer);
|
|
214
|
+
return (tsNode !== undefined && holds(checker.getTypeAtLocation(tsNode), checker));
|
|
215
|
+
});
|
|
216
|
+
};
|
|
170
217
|
//# 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,EACd,QAAQ,GAGT,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"ast-utils.mjs","sourceRoot":"","sources":["../../src/rules/ast-utils.mts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.mts","sourceRoot":"","sources":["../../src/rules/constants.mts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"constants.d.mts","sourceRoot":"","sources":["../../src/rules/constants.mts"],"names":[],"mappings":"AAEA,eAAO,MAAM,oBAAoB,kBAAkB,CAAC;AAEpD,yDAAyD;AACzD,eAAO,MAAM,kBAAkB,QAOP,CAAC"}
|
package/dist/rules/constants.mjs
CHANGED
|
@@ -1,2 +1,11 @@
|
|
|
1
|
+
import * as ts from 'typescript';
|
|
1
2
|
export const TS_DATA_FORGE_MODULE = 'ts-data-forge';
|
|
3
|
+
|
|
4
|
+
export const primitiveTypeFlags = ts.TypeFlags.StringLike |
|
|
5
|
+
ts.TypeFlags.NumberLike |
|
|
6
|
+
ts.TypeFlags.BigIntLike |
|
|
7
|
+
ts.TypeFlags.BooleanLike |
|
|
8
|
+
ts.TypeFlags.ESSymbolLike |
|
|
9
|
+
ts.TypeFlags.Null |
|
|
10
|
+
ts.TypeFlags.Undefined;
|
|
2
11
|
//# sourceMappingURL=constants.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.mjs","sourceRoot":"","sources":["../../src/rules/constants.mts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,oBAAoB,GAAG,eAAe,CAAC"}
|
|
1
|
+
{"version":3,"file":"constants.mjs","sourceRoot":"","sources":["../../src/rules/constants.mts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AAEjC,MAAM,CAAC,MAAM,oBAAoB,GAAG,eAAe,CAAC;AAEpD,yDAAyD;AACzD,MAAM,CAAC,MAAM,kBAAkB,GAC7B,EAAE,CAAC,SAAS,CAAC,UAAU;IACvB,EAAE,CAAC,SAAS,CAAC,UAAU;IACvB,EAAE,CAAC,SAAS,CAAC,UAAU;IACvB,EAAE,CAAC,SAAS,CAAC,WAAW;IACxB,EAAE,CAAC,SAAS,CAAC,YAAY;IACzB,EAAE,CAAC,SAAS,CAAC,IAAI;IACjB,EAAE,CAAC,SAAS,CAAC,SAAS,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type TSESLint, type TSESTree } from '@typescript-eslint/utils';
|
|
2
|
+
import * as ts from 'typescript';
|
|
3
|
+
/**
|
|
4
|
+
* Whether the code around `node` visibly relies on the result being a mutable
|
|
5
|
+
* array, so that swapping in the readonly array `Arr.uniq` or `Arr.generate`
|
|
6
|
+
* returns would not compile. Looks at `node` itself and, when it initializes a variable without a
|
|
7
|
+
* type annotation, at every read of that variable.
|
|
8
|
+
*/
|
|
9
|
+
export declare const needsMutableResult: (sourceCode: TSESLint.SourceCode, checker: ts.TypeChecker, getTsNode: (esNode: TSESTree.Node) => ts.Node | undefined, node: TSESTree.Node) => boolean;
|
|
10
|
+
//# sourceMappingURL=mutable-result.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mutable-result.d.mts","sourceRoot":"","sources":["../../src/rules/mutable-result.mts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,QAAQ,EACb,KAAK,QAAQ,EACd,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AAGjC;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,eAEjB,QAAQ,CAAC,UAAU,WAEtB,EAAE,CAAC,WAAW,aAEZ,CAAC,MAAM,EAAE,QAAQ,CAAC,IAAI,KAAK,EAAE,CAAC,IAAI,GAAG,SAAS,QAEnD,QAAQ,CAAC,IAAI,KAClB,OA+BF,CAAC"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { AST_NODE_TYPES, } from '@typescript-eslint/utils';
|
|
2
|
+
import * as ts from 'typescript';
|
|
3
|
+
import { primitiveTypeFlags } from './constants.mjs';
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
export const needsMutableResult = (
|
|
11
|
+
|
|
12
|
+
sourceCode,
|
|
13
|
+
|
|
14
|
+
checker,
|
|
15
|
+
|
|
16
|
+
getTsNode,
|
|
17
|
+
|
|
18
|
+
node) => {
|
|
19
|
+
const outer = outermostTypePreservingWrapper(node);
|
|
20
|
+
if (isUsedAsMutable(checker, getTsNode, outer)) {
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
const parent = outer.parent;
|
|
24
|
+
if (parent?.type !== AST_NODE_TYPES.VariableDeclarator ||
|
|
25
|
+
parent.init !== outer ||
|
|
26
|
+
parent.id.type !== AST_NODE_TYPES.Identifier ||
|
|
27
|
+
parent.id.typeAnnotation !== undefined) {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
const [variable] = sourceCode.getDeclaredVariables(parent);
|
|
31
|
+
return (variable?.references.some((reference) => reference.init !== true &&
|
|
32
|
+
isUsedAsMutable(checker, getTsNode, outermostTypePreservingWrapper(reference.identifier))) ?? false);
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
const outermostTypePreservingWrapper = (
|
|
41
|
+
|
|
42
|
+
node) => {
|
|
43
|
+
const { parent } = node;
|
|
44
|
+
return parent !== undefined &&
|
|
45
|
+
(parent.type === AST_NODE_TYPES.TSNonNullExpression ||
|
|
46
|
+
parent.type === AST_NODE_TYPES.TSSatisfiesExpression) &&
|
|
47
|
+
parent.expression === node
|
|
48
|
+
? outermostTypePreservingWrapper(parent)
|
|
49
|
+
: node;
|
|
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
|
+
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
const getDeclaredParameterType = (
|
|
97
|
+
|
|
98
|
+
checker,
|
|
99
|
+
|
|
100
|
+
argument) => {
|
|
101
|
+
const call = argument.parent;
|
|
102
|
+
if (!ts.isCallExpression(call) && !ts.isNewExpression(call)) {
|
|
103
|
+
return undefined;
|
|
104
|
+
}
|
|
105
|
+
const index = call.arguments?.indexOf(argument) ?? -1;
|
|
106
|
+
if (index === -1) {
|
|
107
|
+
return undefined;
|
|
108
|
+
}
|
|
109
|
+
const declaration = checker.getResolvedSignature(call)?.getDeclaration();
|
|
110
|
+
const parameter = declaration?.parameters[index];
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
return parameter === undefined || parameter.dotDotDotToken !== undefined
|
|
114
|
+
? undefined
|
|
115
|
+
: checker.getTypeAtLocation(parameter);
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
const isMutableArrayOnly = (
|
|
123
|
+
|
|
124
|
+
checker,
|
|
125
|
+
|
|
126
|
+
type) => {
|
|
127
|
+
const members = type.isUnion() ? type.types : [type];
|
|
128
|
+
return (members.every((t) =>
|
|
129
|
+
|
|
130
|
+
(t.flags & primitiveTypeFlags) !== 0 ||
|
|
131
|
+
(checker.isArrayType(t) && t.getSymbol()?.getName() === 'Array')) && members.some((t) => (t.flags & primitiveTypeFlags) === 0));
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const mutatingMethods = new Set([
|
|
135
|
+
'copyWithin',
|
|
136
|
+
'fill',
|
|
137
|
+
'pop',
|
|
138
|
+
'push',
|
|
139
|
+
'reverse',
|
|
140
|
+
'shift',
|
|
141
|
+
'sort',
|
|
142
|
+
'splice',
|
|
143
|
+
'unshift',
|
|
144
|
+
]);
|
|
145
|
+
//# sourceMappingURL=mutable-result.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mutable-result.mjs","sourceRoot":"","sources":["../../src/rules/mutable-result.mts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { type TSESLint } from '@typescript-eslint/utils';
|
|
2
|
+
type Options = readonly [];
|
|
3
|
+
type MessageIds = 'useArrGenerate' | 'suggestArrGenerate';
|
|
4
|
+
/**
|
|
5
|
+
* The callback of `xs.flatMap((x) => (cond ? [a, b] : []))` decides per
|
|
6
|
+
* element whether to keep it and what to keep. Written as a loop, that is
|
|
7
|
+
*
|
|
8
|
+
* ```ts
|
|
9
|
+
* Arr.generate(function* () {
|
|
10
|
+
* for (const x of xs) {
|
|
11
|
+
* if (cond) {
|
|
12
|
+
* yield a;
|
|
13
|
+
* yield b;
|
|
14
|
+
* }
|
|
15
|
+
* }
|
|
16
|
+
* });
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* A block-bodied callback whose only `return` is its last statement works the
|
|
20
|
+
* same way: the statements before it move into the loop. When the empty array
|
|
21
|
+
* is the consequent (`cond ? [] : [a]`), the condition is negated the short way
|
|
22
|
+
* `negationOf` from eslint-rule-forge writes it (`a !== b`, `!a && !b`).
|
|
23
|
+
*
|
|
24
|
+
* The callback is reported only when the rewrite keeps its meaning:
|
|
25
|
+
*
|
|
26
|
+
* - The receiver is an array or a tuple at every layer of its type wrappers
|
|
27
|
+
* (an object with a `flatMap` method of its own is not touched).
|
|
28
|
+
* - The callback is a non-async arrow function with one parameter, which may
|
|
29
|
+
* be destructured but has no default: an index or array parameter has no
|
|
30
|
+
* counterpart in the loop.
|
|
31
|
+
* - Neither the callback nor the receiver reads `this`, `arguments`, `super`
|
|
32
|
+
* or `new.target`, which the generator function would rebind; the receiver
|
|
33
|
+
* names none of the parameter's bindings, which the loop variable would
|
|
34
|
+
* shadow (`node.children.flatMap((node) => …)`).
|
|
35
|
+
*
|
|
36
|
+
* The fix is applied automatically only when nothing it drops could have
|
|
37
|
+
* mattered; otherwise it is offered as a suggestion:
|
|
38
|
+
*
|
|
39
|
+
* - The result becomes a readonly array, so code that visibly needs a mutable
|
|
40
|
+
* one (see `needsMutableResult`) keeps a suggestion.
|
|
41
|
+
* - A type annotation on the parameter, a return type on the callback, or a
|
|
42
|
+
* type wrapper around the conditional or either branch
|
|
43
|
+
* (`[] as readonly T[]`), may be what types the elements, and the loop has
|
|
44
|
+
* no place for it.
|
|
45
|
+
* - The receiver moves into the generator function, where a narrowing of a
|
|
46
|
+
* property (`s.decl.items` after `s.decl !== null`) or of a variable that is
|
|
47
|
+
* reassigned somewhere no longer applies.
|
|
48
|
+
* - A `filter()` receiver becomes an intermediate array the loop iterates,
|
|
49
|
+
* which reads better as a condition inside the loop.
|
|
50
|
+
* - A comment the rewrite has no place for would be lost.
|
|
51
|
+
*
|
|
52
|
+
* One difference is not checked: `flatMap` skips the holes of a sparse array,
|
|
53
|
+
* while `for…of` visits them as `undefined`.
|
|
54
|
+
*/
|
|
55
|
+
export declare const preferArrGenerate: TSESLint.RuleModule<MessageIds, Options>;
|
|
56
|
+
export {};
|
|
57
|
+
//# sourceMappingURL=prefer-arr-generate.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prefer-arr-generate.d.mts","sourceRoot":"","sources":["../../src/rules/prefer-arr-generate.mts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,QAAQ,EAEd,MAAM,0BAA0B,CAAC;AAkBlC,KAAK,OAAO,GAAG,SAAS,EAAE,CAAC;AAE3B,KAAK,UAAU,GAAG,gBAAgB,GAAG,oBAAoB,CAAC;AAS1D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AACH,eAAO,MAAM,iBAAiB,EAAE,QAAQ,CAAC,UAAU,CAAC,UAAU,EAAE,OAAO,CA4P7D,CAAC"}
|