oxlint-plugin-effect 0.13.0 → 0.15.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 +26 -14
- package/THIRD_PARTY_NOTICES.md +4 -2
- package/dist/presets/recommended.d.ts +10 -0
- package/dist/presets/recommended.js +11 -1
- package/dist/rules/_anti-slop-array-method.js +78 -0
- package/dist/rules/_anti-slop-dictionary-types.js +198 -150
- package/dist/rules/_anti-slop-function-parameters.js +30 -0
- package/dist/rules/_anti-slop-lexical-type-parameters.js +25 -0
- package/dist/rules/_anti-slop-reflect-method.js +25 -0
- package/dist/rules/_anti-slop-scope.js +15 -0
- package/dist/rules/_anti-slop-type-alias-resolution.js +139 -0
- package/dist/rules/_ast-ancestors.js +14 -0
- package/dist/rules/_ast-children.js +18 -0
- package/dist/rules/_call-arguments.js +11 -0
- package/dist/rules/_effect-context.js +25 -20
- package/dist/rules/_function-metrics.js +94 -75
- package/dist/rules/_tagged-control-flow.js +38 -60
- package/dist/rules/_test-apis.js +47 -0
- package/dist/rules/_test-files.js +8 -0
- package/dist/rules/index.d.ts +11 -1
- package/dist/rules/index.js +21 -1
- package/dist/rules/no-array-filter-map.d.ts +7 -0
- package/dist/rules/no-array-filter-map.js +49 -0
- package/dist/rules/no-chained-type-assertions.js +7 -4
- package/dist/rules/no-conditional-empty-object-spread.d.ts +1 -1
- package/dist/rules/no-conditional-empty-object-spread.js +7 -47
- package/dist/rules/no-dynamic-imports.js +33 -25
- package/dist/rules/no-eager-acquire.d.ts +6 -0
- package/dist/rules/no-eager-acquire.js +98 -0
- package/dist/rules/no-effect-run-in-tests.d.ts +6 -0
- package/dist/rules/no-effect-run-in-tests.js +60 -0
- package/dist/rules/no-globals.js +42 -31
- package/dist/rules/no-known-value-widening.js +67 -50
- package/dist/rules/no-module-level-mutable-state.d.ts +6 -0
- package/dist/rules/no-module-level-mutable-state.js +47 -0
- package/dist/rules/no-module-mocks.js +37 -48
- package/dist/rules/no-new-promise.js +6 -2
- package/dist/rules/no-node-builtin-import.js +56 -33
- package/dist/rules/no-nullish.js +5 -1
- package/dist/rules/no-object-parameters.js +16 -30
- package/dist/rules/no-per-call-cache-construction.js +2 -2
- package/dist/rules/no-reduce-accumulator-copy.d.ts +7 -0
- package/dist/rules/no-reduce-accumulator-copy.js +106 -0
- package/dist/rules/no-reflect-apply.d.ts +7 -0
- package/dist/rules/no-reflect-apply.js +28 -0
- package/dist/rules/no-reflect-get.d.ts +7 -0
- package/dist/rules/no-reflect-get.js +28 -0
- package/dist/rules/no-run-collect-on-unbounded-stream.js +23 -25
- package/dist/rules/no-runtime-typeof.js +21 -4
- package/dist/rules/no-sequential-effect-all.js +18 -11
- package/dist/rules/no-shape-in-symbol-names.js +15 -5
- package/dist/rules/no-silent-catch-all.js +20 -14
- package/dist/rules/no-test-globals.d.ts +6 -0
- package/dist/rules/no-test-globals.js +147 -0
- package/dist/rules/no-test-lifecycle-hooks.js +4 -2
- package/dist/rules/no-unbounded-concurrency.js +22 -17
- package/dist/rules/no-unbounded-retry.js +47 -62
- package/dist/rules/no-unknown-parameters.d.ts +1 -1
- package/dist/rules/no-unknown-parameters.js +26 -17
- package/dist/rules/no-unknown-returns.d.ts +7 -0
- package/dist/rules/no-unknown-returns.js +74 -0
- package/dist/rules/no-unknown-type-aliases.js +21 -27
- package/dist/rules/no-unsafe-dictionary-type.js +71 -25
- package/dist/rules/no-widen-then-assert.js +96 -73
- package/dist/rules/prefer-catch-tag.js +29 -37
- package/dist/rules/prefer-match-tags-exhaustive.js +35 -47
- package/dist/rules/prefer-predicate-is-tagged.js +4 -6
- package/dist/rules/prefer-service-of.js +39 -26
- package/dist/rules/require-named-effect-fn.js +4 -2
- package/dist/rules/require-suppression-reason.d.ts +6 -0
- package/dist/rules/require-suppression-reason.js +92 -0
- package/dist/vendor/effect-oxlint/Diagnostic.js +1 -1
- package/dist/vendor/effect-oxlint/Scope.js +1 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -34,10 +34,14 @@ If the project uses JSON configuration, copy the exported rule map into `rules`;
|
|
|
34
34
|
| `effect/noThrowStatement` | Bans every throw statement |
|
|
35
35
|
| `effect/noNewPromise` | Bans new Promise, Promise calls, and Promise static APIs |
|
|
36
36
|
| `effect/noNewError` | Allows native Error values only as direct arguments to Effect.die, Cause.die, or Exit.die |
|
|
37
|
-
| `effect/noNullish` | Bans null and undefined; permits `Object.create(null)` for prototype-free dictionaries
|
|
38
|
-
| `effect/noModuleMocks` | Bans Vitest and
|
|
37
|
+
| `effect/noNullish` | Bans null and undefined; permits `Object.create(null)` for prototype-free dictionaries |
|
|
38
|
+
| `effect/noModuleMocks` | Bans Vitest, Jest, and bun:test module mocks, mock functions, and spies; use test layers |
|
|
39
|
+
| `effect/noTestGlobals` | Bans global writes, global stubs, and implicit runner globals in test files |
|
|
39
40
|
| `effect/noTernary` | Bans conditional expressions while allowing ordinary if statements |
|
|
40
41
|
| `effect/noManagedRuntimeInEffect` | Keeps ManagedRuntime construction at non-Effect host boundaries |
|
|
42
|
+
| `effect/noModuleLevelMutableState` | Bans module-level `let` and `var` outside tests; hold shared state in a Layer-owned `Ref` |
|
|
43
|
+
| `effect/noEagerAcquire` | Bans `acquireRelease` acquires that build or capture the resource before acquire runs |
|
|
44
|
+
| `effect/noEffectRunInTests` | Bans `Effect.run*` and `ManagedRuntime.make` in tests; use `it.effect` or `it.layer` |
|
|
41
45
|
| `effect/noInlineProvide` | Keeps dependency provisioning at explicit composition boundaries |
|
|
42
46
|
| `effect/noNestedEffectGen` | Flattens directly yielded nested generators |
|
|
43
47
|
| `effect/noPerCallCacheConstruction` | Constructs shared caches once in their owning layer |
|
|
@@ -55,26 +59,34 @@ If the project uses JSON configuration, copy the exported rule map into `rules`;
|
|
|
55
59
|
| `effect/preferPredicateIsTagged` | Replaces combined `_tag` comparisons with a named `Predicate` refinement |
|
|
56
60
|
| `effect/preferServiceOf` | Checks inline Layer implementations through `Service.of` |
|
|
57
61
|
| `effect/requireNamedEffectFn` | Requires stable names for `Effect.fn` operations |
|
|
62
|
+
| `effect/requireSuppressionReason` | Requires lint, Effect, and TS suppressions to name their target and give a `--` reason |
|
|
58
63
|
| `effect/noGlobals` | Bans ambient capabilities with direct Effect replacements; allows `process.std*.isTTY` |
|
|
59
64
|
| `effect/noNodeBuiltinImport` | Bans fully replaced Node modules and replaced operations from partial modules |
|
|
60
65
|
|
|
66
|
+
`effect/requireSuppressionReason` also rejects `@effect-diagnostics effect/name:off`: @effect/tsgo ignores the `effect/` prefix, so write the bare rule name. A blanket directive that covers its own line, such as a bare `// oxlint-disable-line` or a file-leading `/* eslint-disable */`, suppresses this rule's report too; oxlint applies the directive before the rule can report it.
|
|
67
|
+
|
|
61
68
|
## Anti-Slop Rules
|
|
62
69
|
|
|
63
70
|
The recommended preset also includes these rules from
|
|
64
71
|
[`dmmulroy/anti-slop`](https://github.com/dmmulroy/anti-slop):
|
|
65
72
|
|
|
66
|
-
| Rule | Contract
|
|
67
|
-
| --------------------------------------- |
|
|
68
|
-
| `effect/
|
|
69
|
-
| `effect/
|
|
70
|
-
| `effect/
|
|
71
|
-
| `effect/
|
|
72
|
-
| `effect/
|
|
73
|
-
| `effect/
|
|
74
|
-
| `effect/
|
|
75
|
-
| `effect/
|
|
76
|
-
| `effect/
|
|
77
|
-
| `effect/
|
|
73
|
+
| Rule | Contract |
|
|
74
|
+
| --------------------------------------- | -------------------------------------------------------------------------------- |
|
|
75
|
+
| `effect/noArrayFilterMap` | Bans adjacent array `filter`/`map` passes over a known array |
|
|
76
|
+
| `effect/noChainedTypeAssertions` | Bans nested type assertions that invent type evidence |
|
|
77
|
+
| `effect/noConditionalEmptyObjectSpread` | Bans conditional spreads that use an empty object to omit fields |
|
|
78
|
+
| `effect/noKnownValueWidening` | Bans broad target types that discard known value evidence |
|
|
79
|
+
| `effect/noObjectParameters` | Bans the broad `object` type on function inputs |
|
|
80
|
+
| `effect/noReduceAccumulatorCopy` | Bans copying a reducer accumulator on every iteration |
|
|
81
|
+
| `effect/noReflectApply` | Bans `Reflect.apply`; call typed functions directly |
|
|
82
|
+
| `effect/noReflectGet` | Bans `Reflect.get`; use typed property access |
|
|
83
|
+
| `effect/noRuntimeTypeof` | Requires boundary parsing instead of `typeof` narrowing; allows existence probes |
|
|
84
|
+
| `effect/noShapeInSymbolNames` | Bans `shape` in symbol names |
|
|
85
|
+
| `effect/noUnknownParameters` | Bans `unknown` inputs except `cause`, type guards, and rejection reasons |
|
|
86
|
+
| `effect/noUnknownReturns` | Bans return contracts of `unknown` or `Promise<unknown>` |
|
|
87
|
+
| `effect/noUnknownTypeAliases` | Bans aliases that only hide `unknown` |
|
|
88
|
+
| `effect/noUnsafeDictionaryType` | Bans dictionaries with unsafe broad value types |
|
|
89
|
+
| `effect/noWidenThenAssert` | Bans local flows that widen known values and then assert them back |
|
|
78
90
|
|
|
79
91
|
See `THIRD_PARTY_NOTICES.md` for the source revision and license.
|
|
80
92
|
|
package/THIRD_PARTY_NOTICES.md
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
# Third-Party Notices
|
|
2
2
|
|
|
3
3
|
The anti-slop rules include code derived from
|
|
4
|
-
[`dmmulroy/anti-slop`](https://github.com/dmmulroy/anti-slop)
|
|
5
|
-
`
|
|
4
|
+
[`dmmulroy/anti-slop`](https://github.com/dmmulroy/anti-slop), synced to commit
|
|
5
|
+
`c44ef22ca116d0ba62a3ff663a0bd13a3f3fa40b`. The rejection-handler exemption in
|
|
6
|
+
`noUnknownParameters` comes from the vendored copy in
|
|
7
|
+
[`joelhooks/rat-stack`](https://github.com/joelhooks/rat-stack).
|
|
6
8
|
|
|
7
9
|
MIT License
|
|
8
10
|
|
|
@@ -14,17 +14,21 @@ declare const recommended: {
|
|
|
14
14
|
readonly "effect/maxHalsteadDifficulty": readonly ["error", {
|
|
15
15
|
readonly max: 79;
|
|
16
16
|
}];
|
|
17
|
+
readonly "effect/noArrayFilterMap": "error";
|
|
17
18
|
readonly "effect/noAs": "error";
|
|
18
19
|
readonly "effect/noAsyncFunction": "error";
|
|
19
20
|
readonly "effect/noChainedTypeAssertions": "error";
|
|
20
21
|
readonly "effect/noConditionalEmptyObjectSpread": "error";
|
|
21
22
|
readonly "effect/noDynamicImports": "error";
|
|
23
|
+
readonly "effect/noEagerAcquire": "error";
|
|
22
24
|
readonly "effect/noEffectBind": "error";
|
|
23
25
|
readonly "effect/noEffectDo": "error";
|
|
26
|
+
readonly "effect/noEffectRunInTests": "error";
|
|
24
27
|
readonly "effect/noGlobals": "error";
|
|
25
28
|
readonly "effect/noInlineProvide": "error";
|
|
26
29
|
readonly "effect/noKnownValueWidening": "error";
|
|
27
30
|
readonly "effect/noManagedRuntimeInEffect": "error";
|
|
31
|
+
readonly "effect/noModuleLevelMutableState": "error";
|
|
28
32
|
readonly "effect/noModuleMocks": "error";
|
|
29
33
|
readonly "effect/noNestedEffectGen": "error";
|
|
30
34
|
readonly "effect/noNewError": "error";
|
|
@@ -33,18 +37,23 @@ declare const recommended: {
|
|
|
33
37
|
readonly "effect/noNullish": "error";
|
|
34
38
|
readonly "effect/noObjectParameters": "error";
|
|
35
39
|
readonly "effect/noPerCallCacheConstruction": "error";
|
|
40
|
+
readonly "effect/noReduceAccumulatorCopy": "error";
|
|
41
|
+
readonly "effect/noReflectApply": "error";
|
|
42
|
+
readonly "effect/noReflectGet": "error";
|
|
36
43
|
readonly "effect/noRunCollectOnUnboundedStream": "error";
|
|
37
44
|
readonly "effect/noRuntimeTypeof": "error";
|
|
38
45
|
readonly "effect/noSequentialEffectAll": "error";
|
|
39
46
|
readonly "effect/noShapeInSymbolNames": "error";
|
|
40
47
|
readonly "effect/noSilentCatchAll": "error";
|
|
41
48
|
readonly "effect/noTernary": "error";
|
|
49
|
+
readonly "effect/noTestGlobals": "error";
|
|
42
50
|
readonly "effect/noTestLifecycleHooks": "error";
|
|
43
51
|
readonly "effect/noThrowStatement": "error";
|
|
44
52
|
readonly "effect/noTryCatch": "error";
|
|
45
53
|
readonly "effect/noUnboundedConcurrency": "error";
|
|
46
54
|
readonly "effect/noUnboundedRetry": "error";
|
|
47
55
|
readonly "effect/noUnknownParameters": "error";
|
|
56
|
+
readonly "effect/noUnknownReturns": "error";
|
|
48
57
|
readonly "effect/noUnknownTypeAliases": "error";
|
|
49
58
|
readonly "effect/noUnsafeDictionaryType": "error";
|
|
50
59
|
readonly "effect/noWidenThenAssert": "error";
|
|
@@ -54,6 +63,7 @@ declare const recommended: {
|
|
|
54
63
|
readonly "effect/preferPredicateIsTagged": "error";
|
|
55
64
|
readonly "effect/preferServiceOf": "error";
|
|
56
65
|
readonly "effect/requireNamedEffectFn": "error";
|
|
66
|
+
readonly "effect/requireSuppressionReason": "error";
|
|
57
67
|
};
|
|
58
68
|
//#endregion
|
|
59
69
|
export { recommended };
|
|
@@ -8,17 +8,21 @@ const recommended = {
|
|
|
8
8
|
complexity: ["error", { max: 21 }],
|
|
9
9
|
"effect/maxCognitiveComplexity": ["error", { max: 21 }],
|
|
10
10
|
"effect/maxHalsteadDifficulty": ["error", { max: 79 }],
|
|
11
|
+
"effect/noArrayFilterMap": "error",
|
|
11
12
|
"effect/noAs": "error",
|
|
12
13
|
"effect/noAsyncFunction": "error",
|
|
13
14
|
"effect/noChainedTypeAssertions": "error",
|
|
14
15
|
"effect/noConditionalEmptyObjectSpread": "error",
|
|
15
16
|
"effect/noDynamicImports": "error",
|
|
17
|
+
"effect/noEagerAcquire": "error",
|
|
16
18
|
"effect/noEffectBind": "error",
|
|
17
19
|
"effect/noEffectDo": "error",
|
|
20
|
+
"effect/noEffectRunInTests": "error",
|
|
18
21
|
"effect/noGlobals": "error",
|
|
19
22
|
"effect/noInlineProvide": "error",
|
|
20
23
|
"effect/noKnownValueWidening": "error",
|
|
21
24
|
"effect/noManagedRuntimeInEffect": "error",
|
|
25
|
+
"effect/noModuleLevelMutableState": "error",
|
|
22
26
|
"effect/noModuleMocks": "error",
|
|
23
27
|
"effect/noNestedEffectGen": "error",
|
|
24
28
|
"effect/noNewError": "error",
|
|
@@ -27,18 +31,23 @@ const recommended = {
|
|
|
27
31
|
"effect/noNullish": "error",
|
|
28
32
|
"effect/noObjectParameters": "error",
|
|
29
33
|
"effect/noPerCallCacheConstruction": "error",
|
|
34
|
+
"effect/noReduceAccumulatorCopy": "error",
|
|
35
|
+
"effect/noReflectApply": "error",
|
|
36
|
+
"effect/noReflectGet": "error",
|
|
30
37
|
"effect/noRunCollectOnUnboundedStream": "error",
|
|
31
38
|
"effect/noRuntimeTypeof": "error",
|
|
32
39
|
"effect/noSequentialEffectAll": "error",
|
|
33
40
|
"effect/noShapeInSymbolNames": "error",
|
|
34
41
|
"effect/noSilentCatchAll": "error",
|
|
35
42
|
"effect/noTernary": "error",
|
|
43
|
+
"effect/noTestGlobals": "error",
|
|
36
44
|
"effect/noTestLifecycleHooks": "error",
|
|
37
45
|
"effect/noThrowStatement": "error",
|
|
38
46
|
"effect/noTryCatch": "error",
|
|
39
47
|
"effect/noUnboundedConcurrency": "error",
|
|
40
48
|
"effect/noUnboundedRetry": "error",
|
|
41
49
|
"effect/noUnknownParameters": "error",
|
|
50
|
+
"effect/noUnknownReturns": "error",
|
|
42
51
|
"effect/noUnknownTypeAliases": "error",
|
|
43
52
|
"effect/noUnsafeDictionaryType": "error",
|
|
44
53
|
"effect/noWidenThenAssert": "error",
|
|
@@ -47,7 +56,8 @@ const recommended = {
|
|
|
47
56
|
"effect/preferMatchTagsExhaustive": "error",
|
|
48
57
|
"effect/preferPredicateIsTagged": "error",
|
|
49
58
|
"effect/preferServiceOf": "error",
|
|
50
|
-
"effect/requireNamedEffectFn": "error"
|
|
59
|
+
"effect/requireNamedEffectFn": "error",
|
|
60
|
+
"effect/requireSuppressionReason": "error"
|
|
51
61
|
};
|
|
52
62
|
//#endregion
|
|
53
63
|
export { recommended };
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import * as Arr from "effect/Array";
|
|
2
|
+
import * as Option from "effect/Option";
|
|
3
|
+
import * as Predicate from "effect/Predicate";
|
|
4
|
+
//#region src/rules/_anti-slop-array-method.ts
|
|
5
|
+
/** Unwrap syntax-only wrappers when inspecting array methods and accumulator references. */
|
|
6
|
+
function unwrapArrayExpression(node) {
|
|
7
|
+
while (node.type === "ParenthesizedExpression" || node.type === "ChainExpression" || node.type === "TSAsExpression" || node.type === "TSTypeAssertion" || node.type === "TSNonNullExpression" || node.type === "TSSatisfiesExpression") node = node.expression;
|
|
8
|
+
return node;
|
|
9
|
+
}
|
|
10
|
+
function* scopeChain(scope) {
|
|
11
|
+
let current = Option.some(scope);
|
|
12
|
+
while (Option.isSome(current)) {
|
|
13
|
+
yield current.value;
|
|
14
|
+
current = Option.fromNullOr(current.value.upper);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
/** Resolve a local binding by scope, not by identifier spelling. */
|
|
18
|
+
function resolveArrayBinding(sourceCode, node) {
|
|
19
|
+
node = unwrapArrayExpression(node);
|
|
20
|
+
if (node.type !== "Identifier") return Option.none();
|
|
21
|
+
const name = node.name;
|
|
22
|
+
return Arr.findFirst(scopeChain(sourceCode.getScope(node)), (scope) => Option.fromUndefinedOr(scope.set.get(name)));
|
|
23
|
+
}
|
|
24
|
+
/** Read static method names, including computed string literals, without evaluating expressions. */
|
|
25
|
+
function arrayMethodTarget(node) {
|
|
26
|
+
node = unwrapArrayExpression(node);
|
|
27
|
+
if (node.type !== "MemberExpression") return Option.none();
|
|
28
|
+
const property = node.property;
|
|
29
|
+
if (!node.computed && property.type === "Identifier") return Option.some({
|
|
30
|
+
name: property.name,
|
|
31
|
+
object: node.object
|
|
32
|
+
});
|
|
33
|
+
if (node.computed && property.type === "Literal" && Predicate.isString(property.value)) return Option.some({
|
|
34
|
+
name: property.value,
|
|
35
|
+
object: node.object
|
|
36
|
+
});
|
|
37
|
+
return Option.none();
|
|
38
|
+
}
|
|
39
|
+
function isArrayAnnotation(type) {
|
|
40
|
+
if (type.type === "TSArrayType" || type.type === "TSTupleType") return true;
|
|
41
|
+
if (type.type === "TSParenthesizedType") return isArrayAnnotation(type.typeAnnotation);
|
|
42
|
+
if (type.type === "TSTypeOperator" && type.operator === "readonly") return isArrayAnnotation(type.typeAnnotation);
|
|
43
|
+
return type.type === "TSTypeReference" && type.typeName.type === "Identifier" && (type.typeName.name === "Array" || type.typeName.name === "ReadonlyArray");
|
|
44
|
+
}
|
|
45
|
+
/** Recognize local array evidence; unknown receivers and iterator pipelines are deliberately excluded. */
|
|
46
|
+
function isKnownArrayExpression(sourceCode, node, visited = /* @__PURE__ */ new Set()) {
|
|
47
|
+
node = unwrapArrayExpression(node);
|
|
48
|
+
if (node.type === "ArrayExpression") return true;
|
|
49
|
+
if (node.type === "CallExpression") return Option.exists(arrayMethodTarget(node.callee), (method) => [
|
|
50
|
+
"map",
|
|
51
|
+
"filter",
|
|
52
|
+
"flatMap",
|
|
53
|
+
"slice",
|
|
54
|
+
"concat",
|
|
55
|
+
"toSorted",
|
|
56
|
+
"toReversed",
|
|
57
|
+
"toSpliced"
|
|
58
|
+
].includes(method.name) && isKnownArrayExpression(sourceCode, method.object, visited));
|
|
59
|
+
if (node.type !== "Identifier") return false;
|
|
60
|
+
return Option.exists(resolveArrayBinding(sourceCode, node), (variable) => isKnownArrayVariable(sourceCode, variable, visited));
|
|
61
|
+
}
|
|
62
|
+
function isKnownArrayVariable(sourceCode, variable, visited) {
|
|
63
|
+
if (visited.has(variable)) return false;
|
|
64
|
+
visited.add(variable);
|
|
65
|
+
if (variable.references.some((reference) => reference.isWrite() && !reference.init)) return false;
|
|
66
|
+
for (const identifier of variable.identifiers) {
|
|
67
|
+
const annotation = identifier.typeAnnotation?.typeAnnotation;
|
|
68
|
+
if (Predicate.isNotUndefined(annotation)) return isArrayAnnotation(annotation);
|
|
69
|
+
}
|
|
70
|
+
return Option.exists(constInitializer(variable), (init) => isKnownArrayExpression(sourceCode, init, visited));
|
|
71
|
+
}
|
|
72
|
+
/** The initializer of the first `const name = init` definition of a variable. */
|
|
73
|
+
function constInitializer(variable) {
|
|
74
|
+
for (const definition of variable.defs) if (definition.type === "Variable" && definition.node.type === "VariableDeclarator" && definition.node.id.type === "Identifier" && Predicate.isNotNull(definition.node.init) && definition.node.parent.type === "VariableDeclaration" && definition.node.parent.kind === "const") return Option.some(definition.node.init);
|
|
75
|
+
return Option.none();
|
|
76
|
+
}
|
|
77
|
+
//#endregion
|
|
78
|
+
export { arrayMethodTarget, constInitializer, isKnownArrayExpression, resolveArrayBinding, unwrapArrayExpression };
|