oxlint-plugin-effect 0.2.0 → 0.2.1
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/_virtual/_rolldown/runtime.js +13 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/plugin.d.ts +5 -0
- package/dist/plugin.js +18 -0
- package/dist/presets/core.d.ts +43 -0
- package/dist/presets/core.js +43 -0
- package/dist/presets/effect-native.d.ts +28 -0
- package/dist/presets/effect-native.js +28 -0
- package/dist/presets/full.d.ts +60 -0
- package/dist/presets/full.js +60 -0
- package/dist/presets/functional.d.ts +21 -0
- package/dist/presets/functional.js +21 -0
- package/dist/presets/index.d.ts +13 -0
- package/dist/presets/index.js +18 -0
- package/dist/presets/strict.d.ts +69 -0
- package/dist/presets/strict.js +69 -0
- package/dist/presets/v3.d.ts +15 -0
- package/dist/presets/v3.js +15 -0
- package/dist/rules/_effect-context.d.ts +19 -0
- package/dist/rules/_effect-context.js +22 -0
- package/dist/rules/index.d.ts +66 -0
- package/dist/rules/index.js +124 -0
- package/dist/rules/no-arrow-ladder.d.ts +6 -0
- package/dist/rules/no-arrow-ladder.js +61 -0
- package/dist/rules/no-async-function.d.ts +6 -0
- package/dist/rules/no-async-function.js +46 -0
- package/dist/rules/no-catch-all-to-map-error.d.ts +6 -0
- package/dist/rules/no-catch-all-to-map-error.js +67 -0
- package/dist/rules/no-effect-as.d.ts +6 -0
- package/dist/rules/no-effect-as.js +16 -0
- package/dist/rules/no-effect-async.d.ts +6 -0
- package/dist/rules/no-effect-async.js +16 -0
- package/dist/rules/no-effect-bind.d.ts +6 -0
- package/dist/rules/no-effect-bind.js +16 -0
- package/dist/rules/no-effect-do.d.ts +6 -0
- package/dist/rules/no-effect-do.js +16 -0
- package/dist/rules/no-effect-fn-generator.d.ts +6 -0
- package/dist/rules/no-effect-fn-generator.js +30 -0
- package/dist/rules/no-effect-gen-adapter.d.ts +6 -0
- package/dist/rules/no-effect-gen-adapter.js +30 -0
- package/dist/rules/no-effect-map-flatten.d.ts +6 -0
- package/dist/rules/no-effect-map-flatten.js +53 -0
- package/dist/rules/no-effect-map-void.d.ts +6 -0
- package/dist/rules/no-effect-map-void.js +40 -0
- package/dist/rules/no-effect-never.d.ts +6 -0
- package/dist/rules/no-effect-never.js +16 -0
- package/dist/rules/no-effect-orElse-ladder.d.ts +6 -0
- package/dist/rules/no-effect-orElse-ladder.js +53 -0
- package/dist/rules/no-effect-succeed-string.d.ts +6 -0
- package/dist/rules/no-effect-succeed-string.js +30 -0
- package/dist/rules/no-effect-succeed-variable.d.ts +6 -0
- package/dist/rules/no-effect-succeed-variable.js +30 -0
- package/dist/rules/no-effect-succeed-void.d.ts +6 -0
- package/dist/rules/no-effect-succeed-void.js +33 -0
- package/dist/rules/no-effect-sync-console.d.ts +6 -0
- package/dist/rules/no-effect-sync-console.js +63 -0
- package/dist/rules/no-effect-sync-wrapper.d.ts +6 -0
- package/dist/rules/no-effect-sync-wrapper.js +37 -0
- package/dist/rules/no-effect-type-alias.d.ts +6 -0
- package/dist/rules/no-effect-type-alias.js +52 -0
- package/dist/rules/no-effect-wrapper-alias.d.ts +6 -0
- package/dist/rules/no-effect-wrapper-alias.js +69 -0
- package/dist/rules/no-extends-native-error.d.ts +6 -0
- package/dist/rules/no-extends-native-error.js +41 -0
- package/dist/rules/no-flatmap-ladder.d.ts +6 -0
- package/dist/rules/no-flatmap-ladder.js +48 -0
- package/dist/rules/no-fromnullable-coalesce.d.ts +6 -0
- package/dist/rules/no-fromnullable-coalesce.js +36 -0
- package/dist/rules/no-global-error-in-catch.d.ts +6 -0
- package/dist/rules/no-global-error-in-catch.js +75 -0
- package/dist/rules/no-global-error-in-failure.d.ts +6 -0
- package/dist/rules/no-global-error-in-failure.js +54 -0
- package/dist/rules/no-globals.d.ts +6 -0
- package/dist/rules/no-globals.js +164 -0
- package/dist/rules/no-if-statement.d.ts +6 -0
- package/dist/rules/no-if-statement.js +18 -0
- package/dist/rules/no-iife-wrapper.d.ts +6 -0
- package/dist/rules/no-iife-wrapper.js +37 -0
- package/dist/rules/no-inline-provide.d.ts +6 -0
- package/dist/rules/no-inline-provide.js +31 -0
- package/dist/rules/no-instanceof-schema.d.ts +6 -0
- package/dist/rules/no-instanceof-schema.js +35 -0
- package/dist/rules/no-manual-effect-channels.d.ts +6 -0
- package/dist/rules/no-manual-effect-channels.js +40 -0
- package/dist/rules/no-match-effect-branch.d.ts +6 -0
- package/dist/rules/no-match-effect-branch.js +64 -0
- package/dist/rules/no-match-void-branch.d.ts +6 -0
- package/dist/rules/no-match-void-branch.js +50 -0
- package/dist/rules/no-multiple-effect-provide.d.ts +6 -0
- package/dist/rules/no-multiple-effect-provide.js +45 -0
- package/dist/rules/no-nested-effect-call.d.ts +6 -0
- package/dist/rules/no-nested-effect-call.js +97 -0
- package/dist/rules/no-nested-effect-gen.d.ts +6 -0
- package/dist/rules/no-nested-effect-gen.js +46 -0
- package/dist/rules/no-nested-pipe.d.ts +6 -0
- package/dist/rules/no-nested-pipe.js +38 -0
- package/dist/rules/no-new-error.d.ts +6 -0
- package/dist/rules/no-new-error.js +39 -0
- package/dist/rules/no-new-promise.d.ts +6 -0
- package/dist/rules/no-new-promise.js +38 -0
- package/dist/rules/no-node-builtin-import.d.ts +6 -0
- package/dist/rules/no-node-builtin-import.js +61 -0
- package/dist/rules/no-option-as.d.ts +6 -0
- package/dist/rules/no-option-as.js +16 -0
- package/dist/rules/no-option-boolean-normalization.d.ts +6 -0
- package/dist/rules/no-option-boolean-normalization.js +50 -0
- package/dist/rules/no-positional-log-error.d.ts +6 -0
- package/dist/rules/no-positional-log-error.js +52 -0
- package/dist/rules/no-redundant-schema-tag-identifier.d.ts +6 -0
- package/dist/rules/no-redundant-schema-tag-identifier.js +46 -0
- package/dist/rules/no-return-in-arrow.d.ts +6 -0
- package/dist/rules/no-return-in-arrow.js +41 -0
- package/dist/rules/no-return-nullish.d.ts +6 -0
- package/dist/rules/no-return-nullish.js +47 -0
- package/dist/rules/no-run-in-effect-gen.d.ts +6 -0
- package/dist/rules/no-run-in-effect-gen.js +48 -0
- package/dist/rules/no-runtime-run-fork.d.ts +6 -0
- package/dist/rules/no-runtime-run-fork.js +19 -0
- package/dist/rules/no-schema-struct-with-tag.d.ts +6 -0
- package/dist/rules/no-schema-struct-with-tag.js +48 -0
- package/dist/rules/no-schema-union-of-literals.d.ts +6 -0
- package/dist/rules/no-schema-union-of-literals.js +35 -0
- package/dist/rules/no-string-sentinel-const.d.ts +6 -0
- package/dist/rules/no-string-sentinel-const.js +38 -0
- package/dist/rules/no-switch-statement.d.ts +6 -0
- package/dist/rules/no-switch-statement.js +16 -0
- package/dist/rules/no-ternary.d.ts +6 -0
- package/dist/rules/no-ternary.js +30 -0
- package/dist/rules/no-throw-statement.d.ts +6 -0
- package/dist/rules/no-throw-statement.js +34 -0
- package/dist/rules/no-try-catch.d.ts +6 -0
- package/dist/rules/no-try-catch.js +34 -0
- package/dist/rules/no-unnecessary-arrow-block.d.ts +6 -0
- package/dist/rules/no-unnecessary-arrow-block.js +34 -0
- package/dist/rules/no-unnecessary-effect-gen.d.ts +6 -0
- package/dist/rules/no-unnecessary-effect-gen.js +35 -0
- package/dist/rules/no-unnecessary-pipe-chain.d.ts +6 -0
- package/dist/rules/no-unnecessary-pipe-chain.js +36 -0
- package/dist/rules/no-unnecessary-pipe.d.ts +6 -0
- package/dist/rules/no-unnecessary-pipe.js +29 -0
- package/dist/vendor/effect-oxlint/AST.d.ts +199 -0
- package/dist/vendor/effect-oxlint/AST.js +214 -0
- package/dist/vendor/effect-oxlint/Comment.d.ts +55 -0
- package/dist/vendor/effect-oxlint/Comment.js +67 -0
- package/dist/vendor/effect-oxlint/Diagnostic.d.ts +86 -0
- package/dist/vendor/effect-oxlint/Diagnostic.js +115 -0
- package/dist/vendor/effect-oxlint/Plugin.d.ts +38 -0
- package/dist/vendor/effect-oxlint/Plugin.js +45 -0
- package/dist/vendor/effect-oxlint/Rule.d.ts +218 -0
- package/dist/vendor/effect-oxlint/Rule.js +309 -0
- package/dist/vendor/effect-oxlint/RuleContext.d.ts +77 -0
- package/dist/vendor/effect-oxlint/RuleContext.js +74 -0
- package/dist/vendor/effect-oxlint/Scope.d.ts +100 -0
- package/dist/vendor/effect-oxlint/Scope.js +110 -0
- package/dist/vendor/effect-oxlint/SourceCode.d.ts +180 -0
- package/dist/vendor/effect-oxlint/SourceCode.js +203 -0
- package/dist/vendor/effect-oxlint/Testing.d.ts +510 -0
- package/dist/vendor/effect-oxlint/Testing.js +963 -0
- package/dist/vendor/effect-oxlint/Token.d.ts +98 -0
- package/dist/vendor/effect-oxlint/Token.js +103 -0
- package/dist/vendor/effect-oxlint/Visitor.d.ts +166 -0
- package/dist/vendor/effect-oxlint/Visitor.js +138 -0
- package/dist/vendor/effect-oxlint/index.d.ts +13 -0
- package/dist/vendor/effect-oxlint/index.js +12 -0
- package/package.json +24 -5
- package/.effect-lsp.json +0 -60
- package/.oxlintrc.json +0 -33
- package/CHANGELOG.md +0 -55
- package/scripts/add-rule.ts +0 -87
- package/scripts/codegen.ts +0 -108
- package/src/index.ts +0 -9
- package/src/plugin.ts +0 -16
- package/src/presets/core.ts +0 -47
- package/src/presets/effect-native.ts +0 -34
- package/src/presets/full.ts +0 -70
- package/src/presets/functional.ts +0 -18
- package/src/presets/index.ts +0 -5
- package/src/presets/strict.ts +0 -77
- package/src/rules/_effect-context.ts +0 -28
- package/src/rules/index.ts +0 -72
- package/src/rules/no-arrow-ladder.ts +0 -70
- package/src/rules/no-async-function.ts +0 -47
- package/src/rules/no-catch-all-to-map-error.ts +0 -90
- package/src/rules/no-effect-as.ts +0 -14
- package/src/rules/no-effect-async.ts +0 -14
- package/src/rules/no-effect-bind.ts +0 -13
- package/src/rules/no-effect-do.ts +0 -14
- package/src/rules/no-effect-fn-generator.ts +0 -58
- package/src/rules/no-effect-gen-adapter.ts +0 -51
- package/src/rules/no-effect-map-flatten.ts +0 -82
- package/src/rules/no-effect-map-void.ts +0 -80
- package/src/rules/no-effect-never.ts +0 -14
- package/src/rules/no-effect-orElse-ladder.ts +0 -79
- package/src/rules/no-effect-succeed-string.ts +0 -52
- package/src/rules/no-effect-succeed-variable.ts +0 -50
- package/src/rules/no-effect-succeed-void.ts +0 -63
- package/src/rules/no-effect-sync-console.ts +0 -91
- package/src/rules/no-effect-sync-wrapper.ts +0 -67
- package/src/rules/no-effect-type-alias.ts +0 -71
- package/src/rules/no-effect-wrapper-alias.ts +0 -95
- package/src/rules/no-extends-native-error.ts +0 -54
- package/src/rules/no-flatmap-ladder.ts +0 -77
- package/src/rules/no-fromnullable-coalesce.ts +0 -62
- package/src/rules/no-global-error-in-catch.ts +0 -104
- package/src/rules/no-global-error-in-failure.ts +0 -83
- package/src/rules/no-globals.ts +0 -178
- package/src/rules/no-if-statement.ts +0 -16
- package/src/rules/no-iife-wrapper.ts +0 -51
- package/src/rules/no-inline-provide.ts +0 -41
- package/src/rules/no-instanceof-schema.ts +0 -42
- package/src/rules/no-manual-effect-channels.ts +0 -58
- package/src/rules/no-match-effect-branch.ts +0 -82
- package/src/rules/no-match-void-branch.ts +0 -72
- package/src/rules/no-multiple-effect-provide.ts +0 -75
- package/src/rules/no-nested-effect-call.ts +0 -57
- package/src/rules/no-nested-effect-gen.ts +0 -43
- package/src/rules/no-nested-pipe.ts +0 -73
- package/src/rules/no-new-error.ts +0 -53
- package/src/rules/no-new-promise.ts +0 -50
- package/src/rules/no-node-builtin-import.ts +0 -68
- package/src/rules/no-option-as.ts +0 -13
- package/src/rules/no-option-boolean-normalization.ts +0 -88
- package/src/rules/no-positional-log-error.ts +0 -76
- package/src/rules/no-redundant-schema-tag-identifier.ts +0 -62
- package/src/rules/no-return-in-arrow.ts +0 -76
- package/src/rules/no-return-nullish.ts +0 -80
- package/src/rules/no-run-in-effect-gen.ts +0 -66
- package/src/rules/no-runtime-run-fork.ts +0 -14
- package/src/rules/no-schema-struct-with-tag.ts +0 -64
- package/src/rules/no-schema-union-of-literals.ts +0 -48
- package/src/rules/no-string-sentinel-const.ts +0 -49
- package/src/rules/no-switch-statement.ts +0 -13
- package/src/rules/no-ternary.ts +0 -30
- package/src/rules/no-throw-statement.ts +0 -39
- package/src/rules/no-try-catch.ts +0 -39
- package/src/rules/no-unnecessary-arrow-block.ts +0 -51
- package/src/rules/no-unnecessary-effect-gen.ts +0 -83
- package/src/rules/no-unnecessary-pipe-chain.ts +0 -47
- package/src/rules/no-unnecessary-pipe.ts +0 -45
- package/src/vendor/effect-oxlint/AST.ts +0 -516
- package/src/vendor/effect-oxlint/Comment.ts +0 -86
- package/src/vendor/effect-oxlint/Diagnostic.ts +0 -199
- package/src/vendor/effect-oxlint/Plugin.ts +0 -71
- package/src/vendor/effect-oxlint/Rule.ts +0 -548
- package/src/vendor/effect-oxlint/RuleContext.ts +0 -144
- package/src/vendor/effect-oxlint/Scope.ts +0 -177
- package/src/vendor/effect-oxlint/SourceCode.ts +0 -377
- package/src/vendor/effect-oxlint/Testing.ts +0 -1227
- package/src/vendor/effect-oxlint/Token.ts +0 -131
- package/src/vendor/effect-oxlint/Visitor.ts +0 -287
- package/src/vendor/effect-oxlint/index.ts +0 -88
- package/tests/ban-rules.test.ts +0 -68
- package/tests/context-rules.test.ts +0 -263
- package/tests/pattern-rules.test.ts +0 -247
- package/tsconfig.json +0 -15
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { isCallOf } from "../vendor/effect-oxlint/AST.js";
|
|
2
|
+
import { make } from "../vendor/effect-oxlint/Diagnostic.js";
|
|
3
|
+
import { RuleContext } from "../vendor/effect-oxlint/RuleContext.js";
|
|
4
|
+
import { define, meta } from "../vendor/effect-oxlint/Rule.js";
|
|
5
|
+
import "../vendor/effect-oxlint/index.js";
|
|
6
|
+
import * as Effect from "effect/Effect";
|
|
7
|
+
//#region src/rules/no-match-void-branch.ts
|
|
8
|
+
const isEffectVoid = (node) => {
|
|
9
|
+
if (node == null || typeof node !== "object") return false;
|
|
10
|
+
const n = node;
|
|
11
|
+
if (n["type"] !== "MemberExpression") return false;
|
|
12
|
+
const obj = n["object"];
|
|
13
|
+
const prop = n["property"];
|
|
14
|
+
return obj != null && obj["type"] === "Identifier" && obj["name"] === "Effect" && prop != null && prop["type"] === "Identifier" && prop["name"] === "void";
|
|
15
|
+
};
|
|
16
|
+
const isVoidCallback = (node) => {
|
|
17
|
+
if (node == null || typeof node !== "object") return false;
|
|
18
|
+
const n = node;
|
|
19
|
+
if (n["type"] !== "ArrowFunctionExpression" && n["type"] !== "FunctionExpression") return false;
|
|
20
|
+
if (!("body" in n)) return false;
|
|
21
|
+
return isEffectVoid(n["body"]);
|
|
22
|
+
};
|
|
23
|
+
const noMatchVoidBranch = define({
|
|
24
|
+
name: "no-match-void-branch",
|
|
25
|
+
meta: meta({
|
|
26
|
+
type: "suggestion",
|
|
27
|
+
description: "Avoid no-op Match branches returning Effect.void. Remove the branch or restructure."
|
|
28
|
+
}),
|
|
29
|
+
create: function* () {
|
|
30
|
+
const ctx = yield* RuleContext;
|
|
31
|
+
return { CallExpression: (node) => {
|
|
32
|
+
const ce = node;
|
|
33
|
+
const isMatchWhen = isCallOf(ce, "Match", "when");
|
|
34
|
+
const isMatchOrElse = isCallOf(ce, "Match", "orElse");
|
|
35
|
+
if (!isMatchWhen && !isMatchOrElse) return Effect.void;
|
|
36
|
+
if (!("arguments" in node) || !Array.isArray(node.arguments)) return Effect.void;
|
|
37
|
+
if (isMatchOrElse && node.arguments.length >= 1 && isVoidCallback(node.arguments[0])) return ctx.report(make({
|
|
38
|
+
node,
|
|
39
|
+
message: "Match.orElse returning Effect.void is a no-op. Remove the branch or restructure."
|
|
40
|
+
}));
|
|
41
|
+
if (isMatchWhen && node.arguments.length >= 2 && isVoidCallback(node.arguments[1])) return ctx.report(make({
|
|
42
|
+
node,
|
|
43
|
+
message: "Match.when branch returning Effect.void is a no-op. Remove the branch or restructure."
|
|
44
|
+
}));
|
|
45
|
+
return Effect.void;
|
|
46
|
+
} };
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
//#endregion
|
|
50
|
+
export { noMatchVoidBranch };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { calleeName, matchCallOf } from "../vendor/effect-oxlint/AST.js";
|
|
2
|
+
import { make } from "../vendor/effect-oxlint/Diagnostic.js";
|
|
3
|
+
import { RuleContext } from "../vendor/effect-oxlint/RuleContext.js";
|
|
4
|
+
import { define, meta } from "../vendor/effect-oxlint/Rule.js";
|
|
5
|
+
import "../vendor/effect-oxlint/index.js";
|
|
6
|
+
import * as Option from "effect/Option";
|
|
7
|
+
import * as Effect from "effect/Effect";
|
|
8
|
+
//#region src/rules/no-multiple-effect-provide.ts
|
|
9
|
+
const isEffectProvide = (node) => {
|
|
10
|
+
if (node.type !== "CallExpression") return false;
|
|
11
|
+
return Option.isSome(matchCallOf(node, "Effect", "provide"));
|
|
12
|
+
};
|
|
13
|
+
const countProvides = (args) => {
|
|
14
|
+
let count = 0;
|
|
15
|
+
for (const arg of args) if (isEffectProvide(arg)) count++;
|
|
16
|
+
return count;
|
|
17
|
+
};
|
|
18
|
+
const noMultipleEffectProvide = define({
|
|
19
|
+
name: "no-multiple-effect-provide",
|
|
20
|
+
meta: meta({
|
|
21
|
+
type: "suggestion",
|
|
22
|
+
description: "Avoid consecutive Effect.provide() calls. Merge into Effect.provide(Layer.mergeAll(...))."
|
|
23
|
+
}),
|
|
24
|
+
create: function* () {
|
|
25
|
+
const ctx = yield* RuleContext;
|
|
26
|
+
return { CallExpression: (node) => {
|
|
27
|
+
const call = node;
|
|
28
|
+
const args = call.arguments;
|
|
29
|
+
if (args.length < 3) return Effect.void;
|
|
30
|
+
const calleeName$1 = Option.getOrUndefined(calleeName(call));
|
|
31
|
+
const callee = call.callee;
|
|
32
|
+
if (!(calleeName$1 === "pipe" || callee.type === "MemberExpression" && "property" in callee && callee["computed"] !== true && (() => {
|
|
33
|
+
const prop = callee["property"];
|
|
34
|
+
return prop != null && typeof prop === "object" && "name" in prop && prop.name === "pipe";
|
|
35
|
+
})())) return Effect.void;
|
|
36
|
+
if (countProvides(args) >= 2) return ctx.report(make({
|
|
37
|
+
node,
|
|
38
|
+
message: "Multiple Effect.provide() in pipe. Merge into Effect.provide(Layer.mergeAll(...))."
|
|
39
|
+
}));
|
|
40
|
+
return Effect.void;
|
|
41
|
+
} };
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
//#endregion
|
|
45
|
+
export { noMultipleEffectProvide };
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { make } from "../vendor/effect-oxlint/Diagnostic.js";
|
|
2
|
+
import { RuleContext } from "../vendor/effect-oxlint/RuleContext.js";
|
|
3
|
+
import { define, meta } from "../vendor/effect-oxlint/Rule.js";
|
|
4
|
+
import "../vendor/effect-oxlint/index.js";
|
|
5
|
+
import * as Effect from "effect/Effect";
|
|
6
|
+
//#region src/rules/no-nested-effect-call.ts
|
|
7
|
+
const pipelineCombinators = new Set([
|
|
8
|
+
"flatMap",
|
|
9
|
+
"map",
|
|
10
|
+
"mapBoth",
|
|
11
|
+
"mapError",
|
|
12
|
+
"andThen",
|
|
13
|
+
"tap",
|
|
14
|
+
"tapError",
|
|
15
|
+
"tapBoth",
|
|
16
|
+
"zipRight",
|
|
17
|
+
"zipLeft",
|
|
18
|
+
"zip",
|
|
19
|
+
"as",
|
|
20
|
+
"asVoid",
|
|
21
|
+
"catchAll",
|
|
22
|
+
"catchAllCause",
|
|
23
|
+
"catch",
|
|
24
|
+
"catchCause",
|
|
25
|
+
"catchTag",
|
|
26
|
+
"catchTags"
|
|
27
|
+
]);
|
|
28
|
+
const effectAcceptingCombinators = new Set([
|
|
29
|
+
"andThen",
|
|
30
|
+
"tap",
|
|
31
|
+
"zipRight",
|
|
32
|
+
"zipLeft"
|
|
33
|
+
]);
|
|
34
|
+
const effectProducers = new Set([
|
|
35
|
+
"gen",
|
|
36
|
+
"fn",
|
|
37
|
+
"succeed",
|
|
38
|
+
"fail",
|
|
39
|
+
"failCause",
|
|
40
|
+
"sync",
|
|
41
|
+
"promise",
|
|
42
|
+
"tryPromise",
|
|
43
|
+
"try",
|
|
44
|
+
"async",
|
|
45
|
+
"void",
|
|
46
|
+
"die",
|
|
47
|
+
"dieMessage"
|
|
48
|
+
]);
|
|
49
|
+
const getEffectMethodName = (node) => {
|
|
50
|
+
if (node == null || typeof node !== "object") return void 0;
|
|
51
|
+
const n = node;
|
|
52
|
+
if (n["type"] !== "CallExpression") return void 0;
|
|
53
|
+
const callee = n["callee"];
|
|
54
|
+
if (callee == null || typeof callee !== "object") return void 0;
|
|
55
|
+
const c = callee;
|
|
56
|
+
if (c["type"] !== "MemberExpression") return void 0;
|
|
57
|
+
const obj = c["object"];
|
|
58
|
+
const prop = c["property"];
|
|
59
|
+
if (obj == null || typeof obj !== "object") return void 0;
|
|
60
|
+
if (prop == null || typeof prop !== "object") return void 0;
|
|
61
|
+
const o = obj;
|
|
62
|
+
const p = prop;
|
|
63
|
+
if (o["type"] !== "Identifier" || o["name"] !== "Effect") return void 0;
|
|
64
|
+
if (p["type"] !== "Identifier" || typeof p["name"] !== "string") return void 0;
|
|
65
|
+
return p["name"];
|
|
66
|
+
};
|
|
67
|
+
const noNestedEffectCall = define({
|
|
68
|
+
name: "no-nested-effect-call",
|
|
69
|
+
meta: meta({
|
|
70
|
+
type: "suggestion",
|
|
71
|
+
description: "Avoid nested Effect pipeline calls. Compose with .pipe() instead of nesting."
|
|
72
|
+
}),
|
|
73
|
+
create: function* () {
|
|
74
|
+
const ctx = yield* RuleContext;
|
|
75
|
+
return { CallExpression: (node) => {
|
|
76
|
+
const outerName = getEffectMethodName(node);
|
|
77
|
+
if (outerName === void 0 || !pipelineCombinators.has(outerName)) return Effect.void;
|
|
78
|
+
const ce = node;
|
|
79
|
+
if (!("arguments" in ce) || !Array.isArray(ce.arguments)) return Effect.void;
|
|
80
|
+
if (ce.arguments.length < 2) return Effect.void;
|
|
81
|
+
const outerTakesEffect = effectAcceptingCombinators.has(outerName);
|
|
82
|
+
for (const arg of ce.arguments) {
|
|
83
|
+
const innerName = getEffectMethodName(arg);
|
|
84
|
+
if (innerName === void 0) continue;
|
|
85
|
+
const isCallTower = pipelineCombinators.has(innerName);
|
|
86
|
+
const isProducerArg = outerTakesEffect && effectProducers.has(innerName);
|
|
87
|
+
if (isCallTower || isProducerArg) return ctx.report(make({
|
|
88
|
+
node,
|
|
89
|
+
message: `Nested Effect.${outerName}(Effect.${innerName}(...)). Use .pipe(Effect.${innerName}(...), Effect.${outerName}(...)) instead.`
|
|
90
|
+
}));
|
|
91
|
+
}
|
|
92
|
+
return Effect.void;
|
|
93
|
+
} };
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
//#endregion
|
|
97
|
+
export { noNestedEffectCall };
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { isCallOf } from "../vendor/effect-oxlint/AST.js";
|
|
2
|
+
import { make } from "../vendor/effect-oxlint/Diagnostic.js";
|
|
3
|
+
import { RuleContext } from "../vendor/effect-oxlint/RuleContext.js";
|
|
4
|
+
import { merge, tracked } from "../vendor/effect-oxlint/Visitor.js";
|
|
5
|
+
import { define, meta } from "../vendor/effect-oxlint/Rule.js";
|
|
6
|
+
import "../vendor/effect-oxlint/index.js";
|
|
7
|
+
import * as Effect from "effect/Effect";
|
|
8
|
+
import * as Ref from "effect/Ref";
|
|
9
|
+
//#region src/rules/no-nested-effect-gen.ts
|
|
10
|
+
const parentOf = (node) => node.parent;
|
|
11
|
+
const isDirectlyNestedGen = (node) => {
|
|
12
|
+
const yieldExpr = parentOf(node);
|
|
13
|
+
if (yieldExpr?.type !== "YieldExpression") return false;
|
|
14
|
+
if (yieldExpr.delegate !== true) return false;
|
|
15
|
+
const stmt = parentOf(yieldExpr);
|
|
16
|
+
if (stmt?.type !== "ExpressionStatement") return false;
|
|
17
|
+
const block = parentOf(stmt);
|
|
18
|
+
if (block?.type !== "BlockStatement") return false;
|
|
19
|
+
const fn = parentOf(block);
|
|
20
|
+
if (fn?.type !== "FunctionExpression" && fn?.type !== "ArrowFunctionExpression") return false;
|
|
21
|
+
const call = parentOf(fn);
|
|
22
|
+
if (call?.type !== "CallExpression") return false;
|
|
23
|
+
return isCallOf(call, "Effect", "gen") || isCallOf(call, "Effect", "fn");
|
|
24
|
+
};
|
|
25
|
+
const noNestedEffectGen = define({
|
|
26
|
+
name: "no-nested-effect-gen",
|
|
27
|
+
meta: meta({
|
|
28
|
+
type: "suggestion",
|
|
29
|
+
description: "Avoid nested Effect.gen. Flatten to a single Effect.gen per method."
|
|
30
|
+
}),
|
|
31
|
+
create: function* () {
|
|
32
|
+
const ctx = yield* RuleContext;
|
|
33
|
+
const depth = yield* Ref.make(0);
|
|
34
|
+
return merge(tracked("CallExpression", (node) => isCallOf(node, "Effect", "gen"), depth), { CallExpression: (node) => Effect.flatMap(Ref.get(depth), (d) => {
|
|
35
|
+
if (d <= 1) return Effect.void;
|
|
36
|
+
if (!isCallOf(node, "Effect", "gen")) return Effect.void;
|
|
37
|
+
if (!isDirectlyNestedGen(node)) return Effect.void;
|
|
38
|
+
return ctx.report(make({
|
|
39
|
+
node,
|
|
40
|
+
message: "Nested Effect.gen detected. Flatten to a single Effect.gen."
|
|
41
|
+
}));
|
|
42
|
+
}) });
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
//#endregion
|
|
46
|
+
export { noNestedEffectGen };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { make } from "../vendor/effect-oxlint/Diagnostic.js";
|
|
2
|
+
import { RuleContext } from "../vendor/effect-oxlint/RuleContext.js";
|
|
3
|
+
import { define, meta } from "../vendor/effect-oxlint/Rule.js";
|
|
4
|
+
import "../vendor/effect-oxlint/index.js";
|
|
5
|
+
import * as Effect from "effect/Effect";
|
|
6
|
+
//#region src/rules/no-nested-pipe.ts
|
|
7
|
+
const isPipeCall = (node) => {
|
|
8
|
+
if (node.type === "CallExpression" && "callee" in node) {
|
|
9
|
+
const callee = node["callee"];
|
|
10
|
+
if (callee != null && typeof callee === "object" && "type" in callee) {
|
|
11
|
+
if (callee.type === "Identifier" && "name" in callee && callee.name === "pipe") return true;
|
|
12
|
+
if (callee.type === "MemberExpression" && "property" in callee && callee.property != null && typeof callee.property === "object" && "type" in callee.property && callee.property.type === "Identifier" && "name" in callee.property && callee.property.name === "pipe") return true;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return false;
|
|
16
|
+
};
|
|
17
|
+
const noNestedPipe = define({
|
|
18
|
+
name: "no-nested-pipe",
|
|
19
|
+
meta: meta({
|
|
20
|
+
type: "suggestion",
|
|
21
|
+
description: "Avoid nested pipe() calls. Flatten into a single pipeline."
|
|
22
|
+
}),
|
|
23
|
+
create: function* () {
|
|
24
|
+
const ctx = yield* RuleContext;
|
|
25
|
+
return { CallExpression: (node) => {
|
|
26
|
+
if (!isPipeCall(node)) return Effect.void;
|
|
27
|
+
if ("arguments" in node && Array.isArray(node.arguments)) {
|
|
28
|
+
for (const arg of node.arguments) if (arg != null && typeof arg === "object" && "type" in arg && isPipeCall(arg)) return ctx.report(make({
|
|
29
|
+
node: arg,
|
|
30
|
+
message: "Nested pipe() detected. Flatten into a single pipeline."
|
|
31
|
+
}));
|
|
32
|
+
}
|
|
33
|
+
return Effect.void;
|
|
34
|
+
} };
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
//#endregion
|
|
38
|
+
export { noNestedPipe };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { make } from "../vendor/effect-oxlint/Diagnostic.js";
|
|
2
|
+
import { RuleContext } from "../vendor/effect-oxlint/RuleContext.js";
|
|
3
|
+
import { merge } from "../vendor/effect-oxlint/Visitor.js";
|
|
4
|
+
import { define, meta } from "../vendor/effect-oxlint/Rule.js";
|
|
5
|
+
import "../vendor/effect-oxlint/index.js";
|
|
6
|
+
import { makeEffectContextTracker } from "./_effect-context.js";
|
|
7
|
+
import * as Effect from "effect/Effect";
|
|
8
|
+
import * as Ref from "effect/Ref";
|
|
9
|
+
//#region src/rules/no-new-error.ts
|
|
10
|
+
const nativeErrors = new Set([
|
|
11
|
+
"Error",
|
|
12
|
+
"TypeError",
|
|
13
|
+
"RangeError",
|
|
14
|
+
"ReferenceError",
|
|
15
|
+
"SyntaxError",
|
|
16
|
+
"URIError",
|
|
17
|
+
"EvalError"
|
|
18
|
+
]);
|
|
19
|
+
const noNewError = define({
|
|
20
|
+
name: "no-new-error",
|
|
21
|
+
meta: meta({
|
|
22
|
+
type: "suggestion",
|
|
23
|
+
description: "Avoid native Error constructors. Use Schema.TaggedErrorClass."
|
|
24
|
+
}),
|
|
25
|
+
create: function* () {
|
|
26
|
+
const ctx = yield* RuleContext;
|
|
27
|
+
const [depth, tracker] = yield* makeEffectContextTracker;
|
|
28
|
+
return merge(tracker, { NewExpression: (node) => Effect.flatMap(Ref.get(depth), (d) => {
|
|
29
|
+
const callee = node["callee"];
|
|
30
|
+
if (callee.type === "Identifier" && "name" in callee && nativeErrors.has(callee.name)) return ctx.report(make({
|
|
31
|
+
node,
|
|
32
|
+
message: d > 0 ? "Avoid native Error inside Effect.gen/fn. Define: class MyError extends Schema.TaggedErrorClass<MyError>()(\"MyError\", { ... }) {} — then yield* new MyError()." : "Avoid native Error constructors. Define: class MyError extends Schema.TaggedErrorClass<MyError>()(\"MyError\", { message: Schema.String }) {}"
|
|
33
|
+
}));
|
|
34
|
+
return Effect.void;
|
|
35
|
+
}) });
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
//#endregion
|
|
39
|
+
export { noNewError };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { make } from "../vendor/effect-oxlint/Diagnostic.js";
|
|
2
|
+
import { RuleContext } from "../vendor/effect-oxlint/RuleContext.js";
|
|
3
|
+
import { merge } from "../vendor/effect-oxlint/Visitor.js";
|
|
4
|
+
import { define, meta } from "../vendor/effect-oxlint/Rule.js";
|
|
5
|
+
import "../vendor/effect-oxlint/index.js";
|
|
6
|
+
import { makeEffectContextTracker } from "./_effect-context.js";
|
|
7
|
+
import * as Effect from "effect/Effect";
|
|
8
|
+
import * as Ref from "effect/Ref";
|
|
9
|
+
//#region src/rules/no-new-promise.ts
|
|
10
|
+
/**
|
|
11
|
+
* Ban `new Promise()`. Context-aware messaging.
|
|
12
|
+
*
|
|
13
|
+
* Inside Effect.gen/fn: "Use Effect.tryPromise or Effect.async"
|
|
14
|
+
* Outside: "Use Effect.tryPromise or wrap with Effect.fn"
|
|
15
|
+
*
|
|
16
|
+
* Source: language-service/newPromise
|
|
17
|
+
*/
|
|
18
|
+
const noNewPromise = define({
|
|
19
|
+
name: "no-new-promise",
|
|
20
|
+
meta: meta({
|
|
21
|
+
type: "suggestion",
|
|
22
|
+
description: "Avoid new Promise(). Use Effect.async or Effect.tryPromise."
|
|
23
|
+
}),
|
|
24
|
+
create: function* () {
|
|
25
|
+
const ctx = yield* RuleContext;
|
|
26
|
+
const [depth, tracker] = yield* makeEffectContextTracker;
|
|
27
|
+
return merge(tracker, { NewExpression: (node) => Effect.flatMap(Ref.get(depth), (d) => {
|
|
28
|
+
const callee = node["callee"];
|
|
29
|
+
if (callee != null && typeof callee === "object" && "type" in callee && callee.type === "Identifier" && "name" in callee && callee.name === "Promise") return ctx.report(make({
|
|
30
|
+
node,
|
|
31
|
+
message: d > 0 ? "Avoid new Promise() inside Effect.gen/fn. Use Effect.async for callback APIs, Effect.tryPromise for existing promises, or Effect.promise for infallible promises." : "Avoid new Promise(). Use Effect.async for callback APIs, Effect.tryPromise for existing promises — wrap this function with Effect.fn."
|
|
32
|
+
}));
|
|
33
|
+
return Effect.void;
|
|
34
|
+
}) });
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
//#endregion
|
|
38
|
+
export { noNewPromise };
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { importSource, narrow } from "../vendor/effect-oxlint/AST.js";
|
|
2
|
+
import { make } from "../vendor/effect-oxlint/Diagnostic.js";
|
|
3
|
+
import { RuleContext } from "../vendor/effect-oxlint/RuleContext.js";
|
|
4
|
+
import { define, meta } from "../vendor/effect-oxlint/Rule.js";
|
|
5
|
+
import "../vendor/effect-oxlint/index.js";
|
|
6
|
+
import * as Option from "effect/Option";
|
|
7
|
+
import * as Effect from "effect/Effect";
|
|
8
|
+
//#region src/rules/no-node-builtin-import.ts
|
|
9
|
+
/**
|
|
10
|
+
* Ban Node.js builtin imports.
|
|
11
|
+
*
|
|
12
|
+
* Use Effect platform services: FileSystem, Path, HttpClient, Command.
|
|
13
|
+
*
|
|
14
|
+
* Source: language-service/nodeBuiltinImport
|
|
15
|
+
*/
|
|
16
|
+
const hints = {
|
|
17
|
+
fs: "Use FileSystem from 'effect'",
|
|
18
|
+
path: "Use Path from 'effect'",
|
|
19
|
+
http: "Use HttpClient from 'effect/unstable/http'",
|
|
20
|
+
https: "Use HttpClient from 'effect/unstable/http'",
|
|
21
|
+
child_process: "Use Command from 'effect'",
|
|
22
|
+
crypto: "Use a service wrapper",
|
|
23
|
+
os: "Use PlatformInfo from 'effect'",
|
|
24
|
+
net: "Use HttpServer from 'effect/unstable/http'",
|
|
25
|
+
dns: "Use a service wrapper",
|
|
26
|
+
tls: "Use a service wrapper",
|
|
27
|
+
dgram: "Use a service wrapper",
|
|
28
|
+
stream: "Use Stream from 'effect'",
|
|
29
|
+
zlib: "Use a service wrapper",
|
|
30
|
+
readline: "Use Terminal from 'effect'",
|
|
31
|
+
cluster: "Use a service wrapper",
|
|
32
|
+
worker_threads: "Use a service wrapper"
|
|
33
|
+
};
|
|
34
|
+
const nodeBuiltins = new Set(Object.keys(hints));
|
|
35
|
+
const resolveModule = (source) => {
|
|
36
|
+
const base = (source.startsWith("node:") ? source.slice(5) : source).split("/")[0];
|
|
37
|
+
return base !== void 0 && nodeBuiltins.has(base) ? base : void 0;
|
|
38
|
+
};
|
|
39
|
+
const noNodeBuiltinImport = define({
|
|
40
|
+
name: "no-node-builtin-import",
|
|
41
|
+
meta: meta({
|
|
42
|
+
type: "suggestion",
|
|
43
|
+
description: "Avoid Node.js builtin imports. Use Effect platform services."
|
|
44
|
+
}),
|
|
45
|
+
create: function* () {
|
|
46
|
+
const ctx = yield* RuleContext;
|
|
47
|
+
return { ImportDeclaration: (node) => {
|
|
48
|
+
const source = Option.getOrUndefined(narrow(node, "ImportDeclaration").pipe(Option.map(importSource)));
|
|
49
|
+
if (source === void 0) return Effect.void;
|
|
50
|
+
const mod = resolveModule(source);
|
|
51
|
+
if (mod === void 0) return Effect.void;
|
|
52
|
+
const hint = hints[mod] ?? "Use an Effect service wrapper";
|
|
53
|
+
return ctx.report(make({
|
|
54
|
+
node,
|
|
55
|
+
message: `Avoid importing '${source}'. ${hint}.`
|
|
56
|
+
}));
|
|
57
|
+
} };
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
//#endregion
|
|
61
|
+
export { noNodeBuiltinImport };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { banMember } from "../vendor/effect-oxlint/Rule.js";
|
|
2
|
+
import "../vendor/effect-oxlint/index.js";
|
|
3
|
+
//#region src/rules/no-option-as.ts
|
|
4
|
+
/**
|
|
5
|
+
* Ban `Option.as`.
|
|
6
|
+
*
|
|
7
|
+
* Use `Option.map` or `Option.match` with explicit value return.
|
|
8
|
+
*
|
|
9
|
+
* Source: biome-effect-linting-rules/no-option-as
|
|
10
|
+
*/
|
|
11
|
+
const noOptionAs = banMember("Option", "as", {
|
|
12
|
+
message: "Avoid Option.as. Use Option.map or Option.match instead.",
|
|
13
|
+
meta: { type: "suggestion" }
|
|
14
|
+
});
|
|
15
|
+
//#endregion
|
|
16
|
+
export { noOptionAs };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { isCallOf } from "../vendor/effect-oxlint/AST.js";
|
|
2
|
+
import { make } from "../vendor/effect-oxlint/Diagnostic.js";
|
|
3
|
+
import { RuleContext } from "../vendor/effect-oxlint/RuleContext.js";
|
|
4
|
+
import { define, meta } from "../vendor/effect-oxlint/Rule.js";
|
|
5
|
+
import "../vendor/effect-oxlint/index.js";
|
|
6
|
+
import * as Effect from "effect/Effect";
|
|
7
|
+
//#region src/rules/no-option-boolean-normalization.ts
|
|
8
|
+
const noOptionBooleanNormalization = define({
|
|
9
|
+
name: "no-option-boolean-normalization",
|
|
10
|
+
meta: meta({
|
|
11
|
+
type: "suggestion",
|
|
12
|
+
description: "Avoid Option.match for boolean normalization. Normalize at schema boundary."
|
|
13
|
+
}),
|
|
14
|
+
create: function* () {
|
|
15
|
+
const ctx = yield* RuleContext;
|
|
16
|
+
return { CallExpression: (node) => {
|
|
17
|
+
if (!isCallOf(node, "Option", "match")) return Effect.void;
|
|
18
|
+
if (!("arguments" in node) || !Array.isArray(node.arguments) || node.arguments.length < 2) return Effect.void;
|
|
19
|
+
const opts = node.arguments[1];
|
|
20
|
+
if (opts == null || typeof opts !== "object" || !("type" in opts)) return Effect.void;
|
|
21
|
+
if (opts.type !== "ObjectExpression" || !("properties" in opts) || !Array.isArray(opts.properties)) return Effect.void;
|
|
22
|
+
let hasTripleEqualTrue = false;
|
|
23
|
+
let hasReturnFalse = false;
|
|
24
|
+
for (const prop of opts.properties) {
|
|
25
|
+
if (prop == null || typeof prop !== "object" || !("type" in prop) || prop.type !== "Property") continue;
|
|
26
|
+
const key = prop["key"];
|
|
27
|
+
const value = prop["value"];
|
|
28
|
+
if (key == null || value == null) continue;
|
|
29
|
+
if (key["type"] === "Identifier" && key["name"] === "onSome" && value["type"] === "ArrowFunctionExpression" && "body" in value) {
|
|
30
|
+
const body = value["body"];
|
|
31
|
+
if (body != null && body["type"] === "BinaryExpression" && body["operator"] === "===" && "right" in body) {
|
|
32
|
+
const right = body["right"];
|
|
33
|
+
if (right != null && right["type"] === "Literal" && right["value"] === true) hasTripleEqualTrue = true;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
if (key["type"] === "Identifier" && key["name"] === "onNone" && value["type"] === "ArrowFunctionExpression" && "body" in value) {
|
|
37
|
+
const body = value["body"];
|
|
38
|
+
if (body != null && body["type"] === "Literal" && body["value"] === false) hasReturnFalse = true;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (hasTripleEqualTrue && hasReturnFalse) return ctx.report(make({
|
|
42
|
+
node,
|
|
43
|
+
message: "Avoid Option.match for boolean normalization. Normalize at schema boundary instead."
|
|
44
|
+
}));
|
|
45
|
+
return Effect.void;
|
|
46
|
+
} };
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
//#endregion
|
|
50
|
+
export { noOptionBooleanNormalization };
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { memberNames } from "../vendor/effect-oxlint/AST.js";
|
|
2
|
+
import { make } from "../vendor/effect-oxlint/Diagnostic.js";
|
|
3
|
+
import { RuleContext } from "../vendor/effect-oxlint/RuleContext.js";
|
|
4
|
+
import { define, meta } from "../vendor/effect-oxlint/Rule.js";
|
|
5
|
+
import "../vendor/effect-oxlint/index.js";
|
|
6
|
+
import * as Option from "effect/Option";
|
|
7
|
+
import * as Effect from "effect/Effect";
|
|
8
|
+
//#region src/rules/no-positional-log-error.ts
|
|
9
|
+
const logMethods = new Set([
|
|
10
|
+
"log",
|
|
11
|
+
"logDebug",
|
|
12
|
+
"logInfo",
|
|
13
|
+
"logWarning",
|
|
14
|
+
"logError",
|
|
15
|
+
"logFatal",
|
|
16
|
+
"logTrace"
|
|
17
|
+
]);
|
|
18
|
+
const noPositionalLogError = define({
|
|
19
|
+
name: "no-positional-log-error",
|
|
20
|
+
meta: meta({
|
|
21
|
+
type: "suggestion",
|
|
22
|
+
description: "Avoid passing errors as positional arguments to Effect.log*. Use Effect.annotateLogs instead."
|
|
23
|
+
}),
|
|
24
|
+
create: function* () {
|
|
25
|
+
const ctx = yield* RuleContext;
|
|
26
|
+
return { CallExpression: (node) => {
|
|
27
|
+
const call = node;
|
|
28
|
+
const names = Option.getOrUndefined(memberNames(call.callee));
|
|
29
|
+
if (names === void 0) return Effect.void;
|
|
30
|
+
const [obj, prop] = names;
|
|
31
|
+
if (obj !== "Effect") return Effect.void;
|
|
32
|
+
if (!logMethods.has(prop)) return Effect.void;
|
|
33
|
+
const args = call.arguments;
|
|
34
|
+
if (args.length < 2) return Effect.void;
|
|
35
|
+
const secondArg = args[1];
|
|
36
|
+
if (secondArg === void 0) return Effect.void;
|
|
37
|
+
if (secondArg.type === "CallExpression") {
|
|
38
|
+
const secondNames = Option.getOrUndefined(memberNames(secondArg.callee));
|
|
39
|
+
if (secondNames !== void 0) {
|
|
40
|
+
const [sObj] = secondNames;
|
|
41
|
+
if (sObj === "Cause") return Effect.void;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return ctx.report(make({
|
|
45
|
+
node: secondArg,
|
|
46
|
+
message: `Avoid passing errors as positional args to Effect.${prop}. Use .pipe(Effect.annotateLogs({ error: String(err) })) or pass a Cause.`
|
|
47
|
+
}));
|
|
48
|
+
} };
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
//#endregion
|
|
52
|
+
export { noPositionalLogError };
|