oxlint-plugin-effect 0.2.3 → 0.4.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.
Files changed (142) hide show
  1. package/README.md +79 -29
  2. package/dist/presets/index.d.ts +3 -9
  3. package/dist/presets/index.js +3 -17
  4. package/dist/presets/recommended.d.ts +17 -0
  5. package/dist/presets/recommended.js +17 -0
  6. package/dist/rules/index.d.ts +4 -59
  7. package/dist/rules/index.js +4 -114
  8. package/dist/rules/no-async-function.js +8 -13
  9. package/dist/rules/no-dynamic-imports.js +89 -60
  10. package/dist/rules/no-globals.js +164 -127
  11. package/dist/rules/no-new-error.js +26 -13
  12. package/dist/rules/no-new-promise.js +22 -21
  13. package/dist/rules/no-node-builtin-import.js +98 -41
  14. package/dist/rules/no-throw-statement.js +4 -16
  15. package/dist/rules/no-try-catch.js +5 -17
  16. package/package.json +2 -2
  17. package/dist/presets/core.d.ts +0 -49
  18. package/dist/presets/core.js +0 -49
  19. package/dist/presets/effect-native.d.ts +0 -28
  20. package/dist/presets/effect-native.js +0 -28
  21. package/dist/presets/full.d.ts +0 -67
  22. package/dist/presets/full.js +0 -67
  23. package/dist/presets/functional.d.ts +0 -22
  24. package/dist/presets/functional.js +0 -22
  25. package/dist/presets/strict.d.ts +0 -71
  26. package/dist/presets/strict.js +0 -71
  27. package/dist/presets/v3-strict.d.ts +0 -16
  28. package/dist/presets/v3-strict.js +0 -16
  29. package/dist/presets/v3.d.ts +0 -18
  30. package/dist/presets/v3.js +0 -18
  31. package/dist/rules/_effect-context.d.ts +0 -19
  32. package/dist/rules/_effect-context.js +0 -22
  33. package/dist/rules/no-arrow-ladder.d.ts +0 -6
  34. package/dist/rules/no-arrow-ladder.js +0 -61
  35. package/dist/rules/no-catch-all-to-map-error.d.ts +0 -6
  36. package/dist/rules/no-catch-all-to-map-error.js +0 -67
  37. package/dist/rules/no-effect-as.d.ts +0 -6
  38. package/dist/rules/no-effect-as.js +0 -16
  39. package/dist/rules/no-effect-async.d.ts +0 -6
  40. package/dist/rules/no-effect-async.js +0 -16
  41. package/dist/rules/no-effect-fn-generator.d.ts +0 -6
  42. package/dist/rules/no-effect-fn-generator.js +0 -30
  43. package/dist/rules/no-effect-gen-adapter.d.ts +0 -6
  44. package/dist/rules/no-effect-gen-adapter.js +0 -30
  45. package/dist/rules/no-effect-map-flatten.d.ts +0 -6
  46. package/dist/rules/no-effect-map-flatten.js +0 -53
  47. package/dist/rules/no-effect-map-void.d.ts +0 -6
  48. package/dist/rules/no-effect-map-void.js +0 -40
  49. package/dist/rules/no-effect-never.d.ts +0 -6
  50. package/dist/rules/no-effect-never.js +0 -16
  51. package/dist/rules/no-effect-orElse-ladder.d.ts +0 -6
  52. package/dist/rules/no-effect-orElse-ladder.js +0 -53
  53. package/dist/rules/no-effect-succeed-string.d.ts +0 -6
  54. package/dist/rules/no-effect-succeed-string.js +0 -30
  55. package/dist/rules/no-effect-succeed-variable.d.ts +0 -6
  56. package/dist/rules/no-effect-succeed-variable.js +0 -30
  57. package/dist/rules/no-effect-succeed-void.d.ts +0 -6
  58. package/dist/rules/no-effect-succeed-void.js +0 -33
  59. package/dist/rules/no-effect-sync-console.d.ts +0 -6
  60. package/dist/rules/no-effect-sync-console.js +0 -63
  61. package/dist/rules/no-effect-sync-wrapper.d.ts +0 -6
  62. package/dist/rules/no-effect-sync-wrapper.js +0 -37
  63. package/dist/rules/no-effect-type-alias.d.ts +0 -6
  64. package/dist/rules/no-effect-type-alias.js +0 -52
  65. package/dist/rules/no-effect-wrapper-alias.d.ts +0 -6
  66. package/dist/rules/no-effect-wrapper-alias.js +0 -69
  67. package/dist/rules/no-extends-native-error.d.ts +0 -6
  68. package/dist/rules/no-extends-native-error.js +0 -41
  69. package/dist/rules/no-flatmap-ladder.d.ts +0 -6
  70. package/dist/rules/no-flatmap-ladder.js +0 -48
  71. package/dist/rules/no-fromnullable-coalesce.d.ts +0 -6
  72. package/dist/rules/no-fromnullable-coalesce.js +0 -36
  73. package/dist/rules/no-global-error-in-catch.d.ts +0 -6
  74. package/dist/rules/no-global-error-in-catch.js +0 -75
  75. package/dist/rules/no-global-error-in-failure.d.ts +0 -6
  76. package/dist/rules/no-global-error-in-failure.js +0 -54
  77. package/dist/rules/no-hand-rolled-tagged-union.d.ts +0 -6
  78. package/dist/rules/no-hand-rolled-tagged-union.js +0 -70
  79. package/dist/rules/no-if-statement.d.ts +0 -6
  80. package/dist/rules/no-if-statement.js +0 -18
  81. package/dist/rules/no-iife-wrapper.d.ts +0 -6
  82. package/dist/rules/no-iife-wrapper.js +0 -37
  83. package/dist/rules/no-inline-provide.d.ts +0 -6
  84. package/dist/rules/no-inline-provide.js +0 -31
  85. package/dist/rules/no-instanceof-schema.d.ts +0 -6
  86. package/dist/rules/no-instanceof-schema.js +0 -35
  87. package/dist/rules/no-make-unsafe.d.ts +0 -6
  88. package/dist/rules/no-make-unsafe.js +0 -30
  89. package/dist/rules/no-manual-effect-channels.d.ts +0 -6
  90. package/dist/rules/no-manual-effect-channels.js +0 -40
  91. package/dist/rules/no-match-effect-branch.d.ts +0 -6
  92. package/dist/rules/no-match-effect-branch.js +0 -64
  93. package/dist/rules/no-match-void-branch.d.ts +0 -6
  94. package/dist/rules/no-match-void-branch.js +0 -50
  95. package/dist/rules/no-multiple-effect-provide.d.ts +0 -6
  96. package/dist/rules/no-multiple-effect-provide.js +0 -45
  97. package/dist/rules/no-nested-effect-call.d.ts +0 -6
  98. package/dist/rules/no-nested-effect-call.js +0 -97
  99. package/dist/rules/no-nested-effect-gen.d.ts +0 -6
  100. package/dist/rules/no-nested-effect-gen.js +0 -46
  101. package/dist/rules/no-nested-pipe.d.ts +0 -6
  102. package/dist/rules/no-nested-pipe.js +0 -38
  103. package/dist/rules/no-option-as.d.ts +0 -6
  104. package/dist/rules/no-option-as.js +0 -16
  105. package/dist/rules/no-option-boolean-normalization.d.ts +0 -6
  106. package/dist/rules/no-option-boolean-normalization.js +0 -50
  107. package/dist/rules/no-positional-log-error.d.ts +0 -6
  108. package/dist/rules/no-positional-log-error.js +0 -52
  109. package/dist/rules/no-promise-control-flow-in-tests.d.ts +0 -6
  110. package/dist/rules/no-promise-control-flow-in-tests.js +0 -94
  111. package/dist/rules/no-redundant-schema-tag-identifier.d.ts +0 -6
  112. package/dist/rules/no-redundant-schema-tag-identifier.js +0 -46
  113. package/dist/rules/no-return-in-arrow.d.ts +0 -6
  114. package/dist/rules/no-return-in-arrow.js +0 -41
  115. package/dist/rules/no-return-nullish.d.ts +0 -6
  116. package/dist/rules/no-return-nullish.js +0 -47
  117. package/dist/rules/no-run-in-effect-gen.d.ts +0 -6
  118. package/dist/rules/no-run-in-effect-gen.js +0 -48
  119. package/dist/rules/no-runtime-run-fork.d.ts +0 -6
  120. package/dist/rules/no-runtime-run-fork.js +0 -19
  121. package/dist/rules/no-schema-struct-with-tag.d.ts +0 -6
  122. package/dist/rules/no-schema-struct-with-tag.js +0 -48
  123. package/dist/rules/no-schema-struct.d.ts +0 -6
  124. package/dist/rules/no-schema-struct.js +0 -28
  125. package/dist/rules/no-schema-union-of-literals.d.ts +0 -6
  126. package/dist/rules/no-schema-union-of-literals.js +0 -35
  127. package/dist/rules/no-sleep-in-tests.d.ts +0 -6
  128. package/dist/rules/no-sleep-in-tests.js +0 -55
  129. package/dist/rules/no-spread.d.ts +0 -6
  130. package/dist/rules/no-spread.js +0 -26
  131. package/dist/rules/no-string-sentinel-const.d.ts +0 -6
  132. package/dist/rules/no-string-sentinel-const.js +0 -38
  133. package/dist/rules/no-switch-statement.d.ts +0 -6
  134. package/dist/rules/no-switch-statement.js +0 -16
  135. package/dist/rules/no-unnecessary-arrow-block.d.ts +0 -6
  136. package/dist/rules/no-unnecessary-arrow-block.js +0 -34
  137. package/dist/rules/no-unnecessary-effect-gen.d.ts +0 -6
  138. package/dist/rules/no-unnecessary-effect-gen.js +0 -35
  139. package/dist/rules/no-unnecessary-pipe-chain.d.ts +0 -6
  140. package/dist/rules/no-unnecessary-pipe-chain.js +0 -36
  141. package/dist/rules/no-unnecessary-pipe.d.ts +0 -6
  142. package/dist/rules/no-unnecessary-pipe.js +0 -29
@@ -1,97 +0,0 @@
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 };
@@ -1,6 +0,0 @@
1
- import * as _$_oxlint_plugins0 from "@oxlint/plugins";
2
-
3
- //#region src/rules/no-nested-effect-gen.d.ts
4
- declare const noNestedEffectGen: _$_oxlint_plugins0.CreateRule;
5
- //#endregion
6
- export { noNestedEffectGen };
@@ -1,46 +0,0 @@
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 };
@@ -1,6 +0,0 @@
1
- import * as _$_oxlint_plugins0 from "@oxlint/plugins";
2
-
3
- //#region src/rules/no-nested-pipe.d.ts
4
- declare const noNestedPipe: _$_oxlint_plugins0.CreateRule;
5
- //#endregion
6
- export { noNestedPipe };
@@ -1,38 +0,0 @@
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 };
@@ -1,6 +0,0 @@
1
- import * as _$_oxlint_plugins0 from "@oxlint/plugins";
2
-
3
- //#region src/rules/no-option-as.d.ts
4
- declare const noOptionAs: _$_oxlint_plugins0.CreateRule;
5
- //#endregion
6
- export { noOptionAs };
@@ -1,16 +0,0 @@
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 };
@@ -1,6 +0,0 @@
1
- import * as _$_oxlint_plugins0 from "@oxlint/plugins";
2
-
3
- //#region src/rules/no-option-boolean-normalization.d.ts
4
- declare const noOptionBooleanNormalization: _$_oxlint_plugins0.CreateRule;
5
- //#endregion
6
- export { noOptionBooleanNormalization };
@@ -1,50 +0,0 @@
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 };
@@ -1,6 +0,0 @@
1
- import * as _$_oxlint_plugins0 from "@oxlint/plugins";
2
-
3
- //#region src/rules/no-positional-log-error.d.ts
4
- declare const noPositionalLogError: _$_oxlint_plugins0.CreateRule;
5
- //#endregion
6
- export { noPositionalLogError };
@@ -1,52 +0,0 @@
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 };
@@ -1,6 +0,0 @@
1
- import * as _$_oxlint_plugins0 from "@oxlint/plugins";
2
-
3
- //#region src/rules/no-promise-control-flow-in-tests.d.ts
4
- declare const noPromiseControlFlowInTests: _$_oxlint_plugins0.CreateRule;
5
- //#endregion
6
- export { noPromiseControlFlowInTests };
@@ -1,94 +0,0 @@
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-promise-control-flow-in-tests.ts
9
- const isTestFilename = (filename) => /\.test\.tsx?$/.test(filename) || /\/tests\/.*\.[cm]?tsx?$/.test(filename);
10
- const promiseChainMethods = new Set([
11
- "then",
12
- "catch",
13
- "finally"
14
- ]);
15
- const promiseStaticMethods = new Set([
16
- "all",
17
- "allSettled",
18
- "any",
19
- "race",
20
- "resolve",
21
- "reject"
22
- ]);
23
- const isAsyncFunction = (node) => "async" in node && node.async === true;
24
- const promiseChainMethodName = (node) => {
25
- if (node.callee.type !== "MemberExpression") return void 0;
26
- const names = Option.getOrUndefined(memberNames(node.callee));
27
- if (names === void 0) return void 0;
28
- const [object, property] = names;
29
- if (object === "Effect") return void 0;
30
- return promiseChainMethods.has(property) ? property : void 0;
31
- };
32
- const noPromiseControlFlowInTests = define({
33
- name: "no-promise-control-flow-in-tests",
34
- meta: meta({
35
- type: "problem",
36
- description: "Keep test control flow in Effect instead of async/await, try/finally, or Promise chains."
37
- }),
38
- create: function* () {
39
- const ctx = yield* RuleContext;
40
- if (!isTestFilename(ctx.filename)) return {};
41
- return {
42
- TryStatement: (node) => {
43
- if (!("finalizer" in node) || node.finalizer == null) return Effect.void;
44
- return ctx.report(make({
45
- node,
46
- message: "Do not use `try/finally` cleanup in tests. Use Effect scopes."
47
- }));
48
- },
49
- FunctionDeclaration: (node) => isAsyncFunction(node) ? ctx.report(make({
50
- node,
51
- message: "Do not use async test functions. Return an Effect from the test body."
52
- })) : Effect.void,
53
- FunctionExpression: (node) => isAsyncFunction(node) ? ctx.report(make({
54
- node,
55
- message: "Do not use async test functions. Return an Effect from the test body."
56
- })) : Effect.void,
57
- ArrowFunctionExpression: (node) => isAsyncFunction(node) ? ctx.report(make({
58
- node,
59
- message: "Do not use async test functions. Return an Effect from the test body."
60
- })) : Effect.void,
61
- AwaitExpression: (node) => ctx.report(make({
62
- node,
63
- message: "Do not use `await` in tests. Use `yield*` inside Effect.gen."
64
- })),
65
- NewExpression: (node) => {
66
- const expression = node;
67
- if (expression.callee.type !== "Identifier" || expression.callee.name !== "Promise") return Effect.void;
68
- return ctx.report(make({
69
- node,
70
- message: "Do not construct Promise directly in tests. Use Effect.async/Effect.promise at real boundaries."
71
- }));
72
- },
73
- CallExpression: (node) => {
74
- const call = node;
75
- const chainMethod = promiseChainMethodName(call);
76
- if (chainMethod !== void 0) return ctx.report(make({
77
- node,
78
- message: `Do not use Promise.${chainMethod} style chains in tests. Keep control flow in Effect.`
79
- }));
80
- if (call.callee.type !== "MemberExpression") return Effect.void;
81
- const names = Option.getOrUndefined(memberNames(call.callee));
82
- if (names === void 0) return Effect.void;
83
- const [object, property] = names;
84
- if (object !== "Promise" || !promiseStaticMethods.has(property)) return Effect.void;
85
- return ctx.report(make({
86
- node,
87
- message: `Do not use Promise.${property} in tests. Use Effect concurrency primitives.`
88
- }));
89
- }
90
- };
91
- }
92
- });
93
- //#endregion
94
- export { noPromiseControlFlowInTests };
@@ -1,6 +0,0 @@
1
- import * as _$_oxlint_plugins0 from "@oxlint/plugins";
2
-
3
- //#region src/rules/no-redundant-schema-tag-identifier.d.ts
4
- declare const noRedundantSchemaTagIdentifier: _$_oxlint_plugins0.CreateRule;
5
- //#endregion
6
- export { noRedundantSchemaTagIdentifier };
@@ -1,46 +0,0 @@
1
- import { 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-redundant-schema-tag-identifier.ts
9
- const isTagKey = (key) => {
10
- if (key.type === "Identifier" && "name" in key && key.name === "_tag") return true;
11
- if (key.type === "Literal" && "value" in key && key.value === "_tag") return true;
12
- return false;
13
- };
14
- const noRedundantSchemaTagIdentifier = define({
15
- name: "no-redundant-schema-tag-identifier",
16
- meta: meta({
17
- type: "suggestion",
18
- description: "Redundant _tag in TaggedStruct. TaggedStruct already provides _tag automatically."
19
- }),
20
- create: function* () {
21
- const ctx = yield* RuleContext;
22
- return { CallExpression: (node) => {
23
- const call = node;
24
- if (Option.isNone(matchCallOf(call, "Schema", "TaggedStruct"))) return Effect.void;
25
- const args = call.arguments;
26
- if (args.length < 2) return Effect.void;
27
- const fieldsArg = args[1];
28
- if (fieldsArg === void 0) return Effect.void;
29
- if (fieldsArg.type !== "ObjectExpression") return Effect.void;
30
- const props = fieldsArg["properties"];
31
- if (!Array.isArray(props)) return Effect.void;
32
- for (const prop of props) {
33
- const p = prop;
34
- if (p.type !== "Property") continue;
35
- const key = p["key"];
36
- if (isTagKey(key)) return ctx.report(make({
37
- node: p,
38
- message: "Redundant _tag property. Schema.TaggedStruct already provides _tag automatically."
39
- }));
40
- }
41
- return Effect.void;
42
- } };
43
- }
44
- });
45
- //#endregion
46
- export { noRedundantSchemaTagIdentifier };
@@ -1,6 +0,0 @@
1
- import * as _$_oxlint_plugins0 from "@oxlint/plugins";
2
-
3
- //#region src/rules/no-return-in-arrow.d.ts
4
- declare const noReturnInArrow: _$_oxlint_plugins0.CreateRule;
5
- //#endregion
6
- export { noReturnInArrow };
@@ -1,41 +0,0 @@
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-return-in-arrow.ts
7
- /**
8
- * Ban explicit `return` in arrow function callbacks (info severity).
9
- *
10
- * Use expression-only callbacks + pipeline logic.
11
- * Excludes Schema.filter callbacks where return is required.
12
- *
13
- * Source: biome-effect-linting-rules/no-return-in-arrow
14
- */
15
- const noReturnInArrow = define({
16
- name: "no-return-in-arrow",
17
- meta: meta({
18
- type: "suggestion",
19
- description: "Prefer expression-only arrow callbacks. Avoid explicit return in arrow functions."
20
- }),
21
- create: function* () {
22
- const ctx = yield* RuleContext;
23
- return { ArrowFunctionExpression: (node) => {
24
- if ("body" in node && node.body != null && typeof node.body === "object" && "type" in node.body && node.body.type === "BlockStatement" && "body" in node.body && Array.isArray(node.body.body)) {
25
- for (const stmt of node.body.body) if (stmt != null && typeof stmt === "object" && "type" in stmt && stmt.type === "ReturnStatement") {
26
- if ("parent" in node && node.parent != null && typeof node.parent === "object" && "type" in node.parent && node.parent.type === "CallExpression" && "callee" in node.parent) {
27
- const callee = node.parent.callee;
28
- if (callee != null && typeof callee === "object" && "type" in callee && callee.type === "MemberExpression" && "property" in callee && callee.property != null && typeof callee.property === "object" && "name" in callee.property && (callee.property.name === "filter" || callee.property.name === "check")) return Effect.void;
29
- }
30
- return ctx.report(make({
31
- node: stmt,
32
- message: "Prefer expression-only arrow callbacks over explicit return."
33
- }));
34
- }
35
- }
36
- return Effect.void;
37
- } };
38
- }
39
- });
40
- //#endregion
41
- export { noReturnInArrow };
@@ -1,6 +0,0 @@
1
- import * as _$_oxlint_plugins0 from "@oxlint/plugins";
2
-
3
- //#region src/rules/no-return-nullish.d.ts
4
- declare const noReturnNullish: _$_oxlint_plugins0.CreateRule;
5
- //#endregion
6
- export { noReturnNullish };
@@ -1,47 +0,0 @@
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-return-nullish.ts
10
- /**
11
- * Ban `return null`, `return undefined`, `return void 0`. Context-aware messaging.
12
- *
13
- * Inside Effect.gen/fn: "Use Option.none() or Effect.void"
14
- * Outside: "Use Option.none() — convert nullish at system boundaries with Option.fromNullable"
15
- *
16
- * Source: biome-effect-linting-rules/no-return-null (extended)
17
- */
18
- const noReturnNullish = define({
19
- name: "no-return-nullish",
20
- meta: meta({
21
- type: "suggestion",
22
- description: "Avoid returning null/undefined. Use Option.none() for absence or Effect.void for void effects."
23
- }),
24
- create: function* () {
25
- const ctx = yield* RuleContext;
26
- const [depth, tracker] = yield* makeEffectContextTracker;
27
- return merge(tracker, { ReturnStatement: (node) => Effect.flatMap(Ref.get(depth), (d) => {
28
- if (node.type !== "ReturnStatement" || !("argument" in node) || node.argument === null || node.argument === void 0) return Effect.void;
29
- const arg = node.argument;
30
- if (arg["type"] === "Literal" && arg["value"] === null) return ctx.report(make({
31
- node,
32
- message: d > 0 ? "Avoid returning null inside Effect.gen/fn. Use Option.none() for absence, or yield* Effect.fail(new MyError()) for errors." : "Avoid returning null. Use Option.none() for absence — convert nullish values at system boundaries with Option.fromNullable()."
33
- }));
34
- if (arg["type"] === "Identifier" && arg["name"] === "undefined") return ctx.report(make({
35
- node,
36
- message: d > 0 ? "Avoid returning undefined inside Effect.gen/fn. Use Effect.void for void effects, or Option.none() for absence." : "Avoid returning undefined. Use Option.none() for absence, or restructure as an Effect returning void."
37
- }));
38
- if (arg["type"] === "UnaryExpression" && arg["operator"] === "void") return ctx.report(make({
39
- node,
40
- message: d > 0 ? "Avoid returning void inside Effect.gen/fn. Use Effect.void for void effects." : "Avoid returning void expression. Use Option.none() for absence."
41
- }));
42
- return Effect.void;
43
- }) });
44
- }
45
- });
46
- //#endregion
47
- export { noReturnNullish };
@@ -1,6 +0,0 @@
1
- import * as _$_oxlint_plugins0 from "@oxlint/plugins";
2
-
3
- //#region src/rules/no-run-in-effect-gen.d.ts
4
- declare const noRunInEffectGen: _$_oxlint_plugins0.CreateRule;
5
- //#endregion
6
- export { noRunInEffectGen };
@@ -1,48 +0,0 @@
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 } 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 { makeEffectContextTracker } from "./_effect-context.js";
8
- import * as Effect from "effect/Effect";
9
- import * as Ref from "effect/Ref";
10
- //#region src/rules/no-run-in-effect-gen.ts
11
- const effectRunMethods = [
12
- "runSync",
13
- "runPromise",
14
- "runFork",
15
- "runCallback"
16
- ];
17
- const runtimeRunMethods = [
18
- "runSync",
19
- "runPromise",
20
- "runFork",
21
- "runCallback"
22
- ];
23
- const noRunInEffectGen = define({
24
- name: "no-run-in-effect-gen",
25
- meta: meta({
26
- type: "problem",
27
- description: "Running effects inside Effect.gen/fn drops the ambient context. Use yield* instead."
28
- }),
29
- create: function* () {
30
- const ctx = yield* RuleContext;
31
- const [depth, tracker] = yield* makeEffectContextTracker;
32
- return merge(tracker, { CallExpression: (node) => Effect.flatMap(Ref.get(depth), (d) => {
33
- if (d <= 0) return Effect.void;
34
- const call = node;
35
- if (isCallOf(call, "Effect", effectRunMethods)) return ctx.report(make({
36
- node,
37
- message: "Avoid Effect.run* inside Effect.gen/fn. `yield*` the child effect, or use Effect.fork for concurrency."
38
- }));
39
- if (isCallOf(call, "Runtime", runtimeRunMethods)) return ctx.report(make({
40
- node,
41
- message: "Avoid Runtime.run* inside Effect.gen/fn. The ambient context already has your services — `yield*` the child effect."
42
- }));
43
- return Effect.void;
44
- }) });
45
- }
46
- });
47
- //#endregion
48
- export { noRunInEffectGen };