@timmo001/oxlint-rules 0.2.0 → 0.3.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 +2 -2
- package/dist/cli.js +211 -211
- package/dist/configs/{effect.js → recommended-effect.js} +211 -211
- package/package.json +3 -3
- package/skills/add-oxlint-rule/SKILL.md +4 -1
- package/skills/install-timmo-oxlint-rules/SKILL.md +3 -2
- package/skills/release-oxlint-rules/SKILL.md +38 -0
|
@@ -1,168 +1,8 @@
|
|
|
1
|
-
// src/effect/index.ts
|
|
2
|
-
import { eslintCompatPlugin } from "@oxlint/plugins";
|
|
3
|
-
|
|
4
|
-
// src/effect/rules/no-try-catch-in-effect-generators.ts
|
|
5
|
-
import { defineRule } from "@oxlint/plugins";
|
|
6
|
-
function resolveVariable(sourceCode, identifier) {
|
|
7
|
-
let scope = sourceCode.getScope(identifier);
|
|
8
|
-
while (scope) {
|
|
9
|
-
const variable = scope.set.get(identifier.name);
|
|
10
|
-
if (variable)
|
|
11
|
-
return variable;
|
|
12
|
-
scope = scope.upper;
|
|
13
|
-
}
|
|
14
|
-
return null;
|
|
15
|
-
}
|
|
16
|
-
function nearestEnclosingFunction(node) {
|
|
17
|
-
let current = node.parent;
|
|
18
|
-
while (current) {
|
|
19
|
-
if (current.type === "FunctionDeclaration" || current.type === "FunctionExpression" || current.type === "ArrowFunctionExpression") {
|
|
20
|
-
return current;
|
|
21
|
-
}
|
|
22
|
-
current = current.parent;
|
|
23
|
-
}
|
|
24
|
-
return null;
|
|
25
|
-
}
|
|
26
|
-
function staticMemberName(node) {
|
|
27
|
-
if (node.type !== "MemberExpression" || node.computed)
|
|
28
|
-
return null;
|
|
29
|
-
return node.property.type === "Identifier" ? node.property.name : null;
|
|
30
|
-
}
|
|
31
|
-
function isEffectImport(sourceCode, identifier, namespace) {
|
|
32
|
-
const variable = resolveVariable(sourceCode, identifier);
|
|
33
|
-
return variable?.defs.some((definition) => {
|
|
34
|
-
if (definition.type !== "ImportBinding" || definition.parent?.type !== "ImportDeclaration" || definition.parent.source.value !== "effect") {
|
|
35
|
-
return false;
|
|
36
|
-
}
|
|
37
|
-
if (namespace)
|
|
38
|
-
return definition.node.type === "ImportNamespaceSpecifier";
|
|
39
|
-
if (definition.node.type !== "ImportSpecifier")
|
|
40
|
-
return false;
|
|
41
|
-
const imported = definition.node.imported;
|
|
42
|
-
return (imported.type === "Identifier" ? imported.name : imported.value) === "Effect";
|
|
43
|
-
}) ?? false;
|
|
44
|
-
}
|
|
45
|
-
function isEffectMethod(sourceCode, node, method) {
|
|
46
|
-
if (staticMemberName(node) !== method || node.type !== "MemberExpression") {
|
|
47
|
-
return false;
|
|
48
|
-
}
|
|
49
|
-
const object = node.object;
|
|
50
|
-
if (object.type === "Identifier") {
|
|
51
|
-
return isEffectImport(sourceCode, object, false);
|
|
52
|
-
}
|
|
53
|
-
if (staticMemberName(object) !== "Effect" || object.type !== "MemberExpression" || object.object.type !== "Identifier") {
|
|
54
|
-
return false;
|
|
55
|
-
}
|
|
56
|
-
return isEffectImport(sourceCode, object.object, true);
|
|
57
|
-
}
|
|
58
|
-
function isDirectArgument(owner, call) {
|
|
59
|
-
return call.arguments.some((argument) => argument === owner);
|
|
60
|
-
}
|
|
61
|
-
function isRecognisedEffectGenerator(sourceCode, owner) {
|
|
62
|
-
const parent = owner.parent;
|
|
63
|
-
if (parent.type !== "CallExpression" || !isDirectArgument(owner, parent)) {
|
|
64
|
-
return false;
|
|
65
|
-
}
|
|
66
|
-
if (isEffectMethod(sourceCode, parent.callee, "gen"))
|
|
67
|
-
return true;
|
|
68
|
-
const factoryCall = parent.callee;
|
|
69
|
-
return factoryCall.type === "CallExpression" && isEffectMethod(sourceCode, factoryCall.callee, "fn");
|
|
70
|
-
}
|
|
71
|
-
var noTryCatchInEffectGeneratorsRule = defineRule({
|
|
72
|
-
meta: {
|
|
73
|
-
type: "problem",
|
|
74
|
-
docs: {
|
|
75
|
-
description: "Disallow synchronous try/catch owned by recognised Effect generator callbacks."
|
|
76
|
-
},
|
|
77
|
-
messages: {
|
|
78
|
-
useEffectErrorChannel: "Keep expected failures in the Effect error channel. Use Effect.try for synchronous throwing work, Effect.tryPromise for asynchronous throwing work, Effect-returning schema APIs for decoding, and Effect recovery combinators for recovery."
|
|
79
|
-
}
|
|
80
|
-
},
|
|
81
|
-
create(context) {
|
|
82
|
-
return {
|
|
83
|
-
TryStatement(node) {
|
|
84
|
-
if (!node.handler)
|
|
85
|
-
return;
|
|
86
|
-
const owner = nearestEnclosingFunction(node);
|
|
87
|
-
if (!owner?.generator || !isRecognisedEffectGenerator(context.sourceCode, owner)) {
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
|
-
context.report({ node, messageId: "useEffectErrorChannel" });
|
|
91
|
-
}
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
// src/effect/index.ts
|
|
97
|
-
var timmoEffectPlugin = eslintCompatPlugin({
|
|
98
|
-
meta: { name: "timmo-effect" },
|
|
99
|
-
rules: {
|
|
100
|
-
"no-try-catch-in-effect-generators": noTryCatchInEffectGeneratorsRule
|
|
101
|
-
}
|
|
102
|
-
});
|
|
103
|
-
var effect_default = timmoEffectPlugin;
|
|
104
|
-
|
|
105
|
-
// vendor/anti-slop/src/effect/index.ts
|
|
106
|
-
import { eslintCompatPlugin as eslintCompatPlugin2 } from "@oxlint/plugins";
|
|
107
|
-
|
|
108
|
-
// vendor/anti-slop/src/effect/rules/no-service-constructor-imports.ts
|
|
109
|
-
import { defineRule as defineRule2 } from "@oxlint/plugins";
|
|
110
|
-
var SERVICE_CONSTRUCTOR_NAME = /^make[A-Z]/u;
|
|
111
|
-
var TEST_FILE = /\.(?:test|spec)\.[cm]?[jt]sx?$/u;
|
|
112
|
-
function isProjectLocalImport(source) {
|
|
113
|
-
return source.startsWith("./") || source.startsWith("../");
|
|
114
|
-
}
|
|
115
|
-
function getImportedName(specifier) {
|
|
116
|
-
if (specifier.imported.type === "Identifier")
|
|
117
|
-
return specifier.imported.name;
|
|
118
|
-
return specifier.imported.value;
|
|
119
|
-
}
|
|
120
|
-
var noServiceConstructorImportsRule = defineRule2({
|
|
121
|
-
meta: {
|
|
122
|
-
type: "problem",
|
|
123
|
-
docs: {
|
|
124
|
-
description: "Disallow project-local make<CapabilityName> imports outside test and spec files."
|
|
125
|
-
},
|
|
126
|
-
messages: {
|
|
127
|
-
serviceConstructorImport: 'Do not import Effect service constructor "{{name}}" into runtime code. Import the owning Layer, yield the contextual service, and allow its requirements to propagate to the composition root.'
|
|
128
|
-
}
|
|
129
|
-
},
|
|
130
|
-
create(context) {
|
|
131
|
-
const isTestFile = TEST_FILE.test(context.filename.replaceAll("\\", "/"));
|
|
132
|
-
return {
|
|
133
|
-
ImportDeclaration(node) {
|
|
134
|
-
if (isTestFile || !isProjectLocalImport(node.source.value))
|
|
135
|
-
return;
|
|
136
|
-
for (const specifier of node.specifiers) {
|
|
137
|
-
if (specifier.type !== "ImportSpecifier")
|
|
138
|
-
continue;
|
|
139
|
-
const importedName = getImportedName(specifier);
|
|
140
|
-
if (!SERVICE_CONSTRUCTOR_NAME.test(importedName))
|
|
141
|
-
continue;
|
|
142
|
-
context.report({
|
|
143
|
-
node: specifier,
|
|
144
|
-
messageId: "serviceConstructorImport",
|
|
145
|
-
data: { name: importedName }
|
|
146
|
-
});
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
};
|
|
150
|
-
}
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
// vendor/anti-slop/src/effect/index.ts
|
|
154
|
-
var antiSlopEffectPlugin = eslintCompatPlugin2({
|
|
155
|
-
meta: { name: "anti-slop-effect" },
|
|
156
|
-
rules: {
|
|
157
|
-
"no-service-constructor-imports": noServiceConstructorImportsRule
|
|
158
|
-
}
|
|
159
|
-
});
|
|
160
|
-
var effect_default2 = antiSlopEffectPlugin;
|
|
161
1
|
// vendor/anti-slop/src/index.ts
|
|
162
|
-
import { eslintCompatPlugin
|
|
2
|
+
import { eslintCompatPlugin } from "@oxlint/plugins";
|
|
163
3
|
|
|
164
4
|
// vendor/anti-slop/src/rules/no-chained-type-assertions.ts
|
|
165
|
-
import { defineRule
|
|
5
|
+
import { defineRule } from "@oxlint/plugins";
|
|
166
6
|
function isTypeAssertionExpression(node) {
|
|
167
7
|
return node.type === "TSAsExpression" || node.type === "TSTypeAssertion";
|
|
168
8
|
}
|
|
@@ -197,7 +37,7 @@ function isForbiddenAssertionChain(node) {
|
|
|
197
37
|
}
|
|
198
38
|
return assertionCount > 1 && hasNonConstAssertion;
|
|
199
39
|
}
|
|
200
|
-
var noChainedTypeAssertionsRule =
|
|
40
|
+
var noChainedTypeAssertionsRule = defineRule({
|
|
201
41
|
meta: {
|
|
202
42
|
type: "problem",
|
|
203
43
|
docs: {
|
|
@@ -221,7 +61,7 @@ var noChainedTypeAssertionsRule = defineRule3({
|
|
|
221
61
|
});
|
|
222
62
|
|
|
223
63
|
// vendor/anti-slop/src/rules/no-conditional-empty-object-spread.ts
|
|
224
|
-
import { defineRule as
|
|
64
|
+
import { defineRule as defineRule2 } from "@oxlint/plugins";
|
|
225
65
|
function unwrapParentheses(node) {
|
|
226
66
|
let current = node;
|
|
227
67
|
while (current.type === "ParenthesizedExpression") {
|
|
@@ -236,7 +76,7 @@ function isConditionalEmptyObjectSpread(node) {
|
|
|
236
76
|
const conditional = unwrapParentheses(node);
|
|
237
77
|
return conditional.type === "ConditionalExpression" && (isEmptyObjectExpression(conditional.consequent) || isEmptyObjectExpression(conditional.alternate));
|
|
238
78
|
}
|
|
239
|
-
var noConditionalEmptyObjectSpreadRule =
|
|
79
|
+
var noConditionalEmptyObjectSpreadRule = defineRule2({
|
|
240
80
|
meta: {
|
|
241
81
|
type: "suggestion",
|
|
242
82
|
docs: {
|
|
@@ -260,7 +100,7 @@ var noConditionalEmptyObjectSpreadRule = defineRule4({
|
|
|
260
100
|
});
|
|
261
101
|
|
|
262
102
|
// vendor/anti-slop/src/rules/no-known-value-widening.ts
|
|
263
|
-
import { defineRule as
|
|
103
|
+
import { defineRule as defineRule3 } from "@oxlint/plugins";
|
|
264
104
|
|
|
265
105
|
// vendor/anti-slop/src/shared/lexical-type-parameters.ts
|
|
266
106
|
function isNode(value) {
|
|
@@ -797,7 +637,7 @@ function unwrapExpression(expression) {
|
|
|
797
637
|
}
|
|
798
638
|
return current;
|
|
799
639
|
}
|
|
800
|
-
function
|
|
640
|
+
function resolveVariable(sourceCode, identifier) {
|
|
801
641
|
let scope = sourceCode.getScope(identifier);
|
|
802
642
|
while (scope !== null) {
|
|
803
643
|
const variable = scope.set.get(identifier.name);
|
|
@@ -822,7 +662,7 @@ function hasKnownEvidence(sourceCode, expression, visitedVariables = new Set) {
|
|
|
822
662
|
const unwrapped = unwrapExpression(expression);
|
|
823
663
|
if (unwrapped.type !== "Identifier")
|
|
824
664
|
return false;
|
|
825
|
-
const variable =
|
|
665
|
+
const variable = resolveVariable(sourceCode, unwrapped);
|
|
826
666
|
if (variable === null || visitedVariables.has(variable))
|
|
827
667
|
return false;
|
|
828
668
|
const declarator = variableDeclarator(variable);
|
|
@@ -841,7 +681,7 @@ function localFunctionForCall(sourceCode, callee) {
|
|
|
841
681
|
return unwrapped;
|
|
842
682
|
if (unwrapped.type !== "Identifier")
|
|
843
683
|
return null;
|
|
844
|
-
const variable =
|
|
684
|
+
const variable = resolveVariable(sourceCode, unwrapped);
|
|
845
685
|
if (variable === null || variable.defs.length !== 1)
|
|
846
686
|
return null;
|
|
847
687
|
const [definition] = variable.defs;
|
|
@@ -894,7 +734,7 @@ function hasKnownCallArgumentEvidence(sourceCode, expression, environment, visit
|
|
|
894
734
|
}
|
|
895
735
|
if (expression.type !== "Identifier")
|
|
896
736
|
return isKnownEvidenceExpression(expression);
|
|
897
|
-
const variable =
|
|
737
|
+
const variable = resolveVariable(sourceCode, expression);
|
|
898
738
|
if (variable === null || visitedVariables.has(variable))
|
|
899
739
|
return false;
|
|
900
740
|
const annotation = variableTypeAnnotation(sourceCode, variable);
|
|
@@ -959,7 +799,7 @@ function isDictionaryAccumulatorTarget(destination) {
|
|
|
959
799
|
function hasParentAssertion(node) {
|
|
960
800
|
return node.parent?.type === "TSAsExpression" || node.parent?.type === "TSTypeAssertion";
|
|
961
801
|
}
|
|
962
|
-
var noKnownValueWideningRule =
|
|
802
|
+
var noKnownValueWideningRule = defineRule3({
|
|
963
803
|
meta: {
|
|
964
804
|
type: "problem",
|
|
965
805
|
docs: {
|
|
@@ -1008,7 +848,7 @@ var noKnownValueWideningRule = defineRule5({
|
|
|
1008
848
|
AssignmentExpression(node) {
|
|
1009
849
|
if (node.operator !== "=" || node.left.type !== "Identifier")
|
|
1010
850
|
return;
|
|
1011
|
-
const variable =
|
|
851
|
+
const variable = resolveVariable(context.sourceCode, node.left);
|
|
1012
852
|
if (variable === null)
|
|
1013
853
|
return;
|
|
1014
854
|
const declarator = variableDeclarator(variable);
|
|
@@ -1072,9 +912,9 @@ var noKnownValueWideningRule = defineRule5({
|
|
|
1072
912
|
});
|
|
1073
913
|
|
|
1074
914
|
// vendor/anti-slop/src/rules/no-module-mocking.ts
|
|
1075
|
-
import { defineRule as
|
|
915
|
+
import { defineRule as defineRule4 } from "@oxlint/plugins";
|
|
1076
916
|
var moduleMockMethods = new Set(["doMock", "mock", "unstable_mockModule"]);
|
|
1077
|
-
function
|
|
917
|
+
function resolveVariable2(sourceCode, identifier) {
|
|
1078
918
|
let scope = sourceCode.getScope(identifier);
|
|
1079
919
|
while (scope !== null) {
|
|
1080
920
|
const variable = scope.set.get(identifier.name);
|
|
@@ -1095,7 +935,7 @@ function isTestFrameworkObject(sourceCode, expression) {
|
|
|
1095
935
|
if ((expression.name === "vi" || expression.name === "jest") && sourceCode.isGlobalReference(expression)) {
|
|
1096
936
|
return true;
|
|
1097
937
|
}
|
|
1098
|
-
const variable =
|
|
938
|
+
const variable = resolveVariable2(sourceCode, expression);
|
|
1099
939
|
if (variable === null || variable.defs.length === 0) {
|
|
1100
940
|
return expression.name === "vi" || expression.name === "jest";
|
|
1101
941
|
}
|
|
@@ -1117,7 +957,7 @@ function moduleMockCall(sourceCode, callee) {
|
|
|
1117
957
|
const method = callee.computed ? property.type === "Literal" && (property.value === "doMock" || property.value === "mock" || property.value === "unstable_mockModule") ? property.value : null : property.type === "Identifier" ? property.name : null;
|
|
1118
958
|
return method !== null && moduleMockMethods.has(method);
|
|
1119
959
|
}
|
|
1120
|
-
var noModuleMockingRule =
|
|
960
|
+
var noModuleMockingRule = defineRule4({
|
|
1121
961
|
meta: {
|
|
1122
962
|
type: "problem",
|
|
1123
963
|
docs: {
|
|
@@ -1141,8 +981,8 @@ var noModuleMockingRule = defineRule6({
|
|
|
1141
981
|
});
|
|
1142
982
|
|
|
1143
983
|
// vendor/anti-slop/src/rules/no-object-parameters.ts
|
|
1144
|
-
import { defineRule as
|
|
1145
|
-
var noObjectParametersRule =
|
|
984
|
+
import { defineRule as defineRule5 } from "@oxlint/plugins";
|
|
985
|
+
var noObjectParametersRule = defineRule5({
|
|
1146
986
|
meta: {
|
|
1147
987
|
type: "problem",
|
|
1148
988
|
docs: {
|
|
@@ -1195,10 +1035,10 @@ var noObjectParametersRule = defineRule7({
|
|
|
1195
1035
|
});
|
|
1196
1036
|
|
|
1197
1037
|
// vendor/anti-slop/src/rules/no-reflect-apply.ts
|
|
1198
|
-
import { defineRule as
|
|
1038
|
+
import { defineRule as defineRule6 } from "@oxlint/plugins";
|
|
1199
1039
|
|
|
1200
1040
|
// vendor/anti-slop/src/shared/reflect-method.ts
|
|
1201
|
-
function
|
|
1041
|
+
function resolveVariable3(sourceCode, identifier) {
|
|
1202
1042
|
let scope = sourceCode.getScope(identifier);
|
|
1203
1043
|
while (scope !== null) {
|
|
1204
1044
|
const variable = scope.set.get(identifier.name);
|
|
@@ -1213,7 +1053,7 @@ function isGlobalReflect(sourceCode, expression) {
|
|
|
1213
1053
|
return false;
|
|
1214
1054
|
if (sourceCode.isGlobalReference(expression))
|
|
1215
1055
|
return true;
|
|
1216
|
-
const variable =
|
|
1056
|
+
const variable = resolveVariable3(sourceCode, expression);
|
|
1217
1057
|
return variable === null || variable.defs.length === 0;
|
|
1218
1058
|
}
|
|
1219
1059
|
function isGlobalReflectMethodCall(sourceCode, callee, methodName) {
|
|
@@ -1226,7 +1066,7 @@ function isGlobalReflectMethodCall(sourceCode, callee, methodName) {
|
|
|
1226
1066
|
}
|
|
1227
1067
|
|
|
1228
1068
|
// vendor/anti-slop/src/rules/no-reflect-apply.ts
|
|
1229
|
-
var noReflectApplyRule =
|
|
1069
|
+
var noReflectApplyRule = defineRule6({
|
|
1230
1070
|
meta: {
|
|
1231
1071
|
type: "problem",
|
|
1232
1072
|
docs: {
|
|
@@ -1250,8 +1090,8 @@ var noReflectApplyRule = defineRule8({
|
|
|
1250
1090
|
});
|
|
1251
1091
|
|
|
1252
1092
|
// vendor/anti-slop/src/rules/no-reflect-get.ts
|
|
1253
|
-
import { defineRule as
|
|
1254
|
-
var noReflectGetRule =
|
|
1093
|
+
import { defineRule as defineRule7 } from "@oxlint/plugins";
|
|
1094
|
+
var noReflectGetRule = defineRule7({
|
|
1255
1095
|
meta: {
|
|
1256
1096
|
type: "problem",
|
|
1257
1097
|
docs: {
|
|
@@ -1275,7 +1115,7 @@ var noReflectGetRule = defineRule9({
|
|
|
1275
1115
|
});
|
|
1276
1116
|
|
|
1277
1117
|
// vendor/anti-slop/src/rules/no-runtime-typeof.ts
|
|
1278
|
-
import { defineRule as
|
|
1118
|
+
import { defineRule as defineRule8 } from "@oxlint/plugins";
|
|
1279
1119
|
function isRuntimeFunction(node) {
|
|
1280
1120
|
return node.type === "ArrowFunctionExpression" || node.type === "FunctionDeclaration" || node.type === "FunctionExpression";
|
|
1281
1121
|
}
|
|
@@ -1298,7 +1138,7 @@ function isExistenceProbe(node) {
|
|
|
1298
1138
|
const other = parent.left === node ? parent.right : parent.left;
|
|
1299
1139
|
return other.type === "Literal" && other.value === "undefined";
|
|
1300
1140
|
}
|
|
1301
|
-
var noRuntimeTypeofRule =
|
|
1141
|
+
var noRuntimeTypeofRule = defineRule8({
|
|
1302
1142
|
meta: {
|
|
1303
1143
|
type: "problem",
|
|
1304
1144
|
docs: {
|
|
@@ -1332,7 +1172,7 @@ var noRuntimeTypeofRule = defineRule10({
|
|
|
1332
1172
|
});
|
|
1333
1173
|
|
|
1334
1174
|
// vendor/anti-slop/src/rules/no-shape-in-symbol-names.ts
|
|
1335
|
-
import { defineRule as
|
|
1175
|
+
import { defineRule as defineRule9 } from "@oxlint/plugins";
|
|
1336
1176
|
var FORBIDDEN_SYMBOL_NAME = "shape";
|
|
1337
1177
|
function containsForbiddenSymbolName(name) {
|
|
1338
1178
|
return name.toLowerCase().includes(FORBIDDEN_SYMBOL_NAME);
|
|
@@ -1343,7 +1183,7 @@ function isBorrowedMemberName(node) {
|
|
|
1343
1183
|
return false;
|
|
1344
1184
|
return parent.property === node && parent.computed === false;
|
|
1345
1185
|
}
|
|
1346
|
-
var noForbiddenTermInSymbolNamesRule =
|
|
1186
|
+
var noForbiddenTermInSymbolNamesRule = defineRule9({
|
|
1347
1187
|
meta: {
|
|
1348
1188
|
type: "problem",
|
|
1349
1189
|
docs: {
|
|
@@ -1372,12 +1212,12 @@ var noForbiddenTermInSymbolNamesRule = defineRule11({
|
|
|
1372
1212
|
});
|
|
1373
1213
|
|
|
1374
1214
|
// vendor/anti-slop/src/rules/no-unknown-parameters.ts
|
|
1375
|
-
import { defineRule as
|
|
1215
|
+
import { defineRule as defineRule10 } from "@oxlint/plugins";
|
|
1376
1216
|
function isTypePredicateSubject(owner, parameterName) {
|
|
1377
1217
|
const predicate = owner.returnType?.typeAnnotation;
|
|
1378
1218
|
return predicate?.type === "TSTypePredicate" && predicate.parameterName.type === "Identifier" && predicate.parameterName.name === parameterName;
|
|
1379
1219
|
}
|
|
1380
|
-
var noUnknownParametersRule =
|
|
1220
|
+
var noUnknownParametersRule = defineRule10({
|
|
1381
1221
|
meta: {
|
|
1382
1222
|
type: "problem",
|
|
1383
1223
|
docs: {
|
|
@@ -1421,8 +1261,8 @@ var noUnknownParametersRule = defineRule12({
|
|
|
1421
1261
|
});
|
|
1422
1262
|
|
|
1423
1263
|
// vendor/anti-slop/src/rules/no-unknown-returns.ts
|
|
1424
|
-
import { defineRule as
|
|
1425
|
-
var noUnknownReturnsRule =
|
|
1264
|
+
import { defineRule as defineRule11 } from "@oxlint/plugins";
|
|
1265
|
+
var noUnknownReturnsRule = defineRule11({
|
|
1426
1266
|
meta: {
|
|
1427
1267
|
type: "problem",
|
|
1428
1268
|
docs: {
|
|
@@ -1475,8 +1315,8 @@ var noUnknownReturnsRule = defineRule13({
|
|
|
1475
1315
|
});
|
|
1476
1316
|
|
|
1477
1317
|
// vendor/anti-slop/src/rules/no-unknown-type-aliases.ts
|
|
1478
|
-
import { defineRule as
|
|
1479
|
-
var noUnknownTypeAliasesRule =
|
|
1318
|
+
import { defineRule as defineRule12 } from "@oxlint/plugins";
|
|
1319
|
+
var noUnknownTypeAliasesRule = defineRule12({
|
|
1480
1320
|
meta: {
|
|
1481
1321
|
type: "problem",
|
|
1482
1322
|
docs: {
|
|
@@ -1514,7 +1354,7 @@ var noUnknownTypeAliasesRule = defineRule14({
|
|
|
1514
1354
|
});
|
|
1515
1355
|
|
|
1516
1356
|
// vendor/anti-slop/src/rules/no-unsafe-dictionary-type.ts
|
|
1517
|
-
import { defineRule as
|
|
1357
|
+
import { defineRule as defineRule13 } from "@oxlint/plugins";
|
|
1518
1358
|
var typeNodeKinds = new Set([
|
|
1519
1359
|
"JSDocNonNullableType",
|
|
1520
1360
|
"JSDocNullableType",
|
|
@@ -1601,7 +1441,7 @@ function shouldReportType(node, environment) {
|
|
|
1601
1441
|
}
|
|
1602
1442
|
return true;
|
|
1603
1443
|
}
|
|
1604
|
-
var noUnsafeDictionaryTypeRule =
|
|
1444
|
+
var noUnsafeDictionaryTypeRule = defineRule13({
|
|
1605
1445
|
meta: {
|
|
1606
1446
|
type: "problem",
|
|
1607
1447
|
docs: {
|
|
@@ -1643,7 +1483,7 @@ var noUnsafeDictionaryTypeRule = defineRule15({
|
|
|
1643
1483
|
});
|
|
1644
1484
|
|
|
1645
1485
|
// vendor/anti-slop/src/rules/no-widen-then-assert.ts
|
|
1646
|
-
import { defineRule as
|
|
1486
|
+
import { defineRule as defineRule14 } from "@oxlint/plugins";
|
|
1647
1487
|
var functionBoundaryTypes = new Set([
|
|
1648
1488
|
"ArrowFunctionExpression",
|
|
1649
1489
|
"FunctionDeclaration",
|
|
@@ -1839,7 +1679,7 @@ function assertionIsNarrower(sourceText, broadKind, evidence, assertedType) {
|
|
|
1839
1679
|
return isDefinitelyObjectType(assertedType);
|
|
1840
1680
|
return isDefinitelyNarrowerRecordType(assertedType);
|
|
1841
1681
|
}
|
|
1842
|
-
var noWidenThenAssertRule =
|
|
1682
|
+
var noWidenThenAssertRule = defineRule14({
|
|
1843
1683
|
meta: {
|
|
1844
1684
|
type: "problem",
|
|
1845
1685
|
docs: {
|
|
@@ -1879,7 +1719,7 @@ var noWidenThenAssertRule = defineRule16({
|
|
|
1879
1719
|
});
|
|
1880
1720
|
|
|
1881
1721
|
// vendor/anti-slop/src/rules/require-safety-comment-for-type-assertion.ts
|
|
1882
|
-
import { defineRule as
|
|
1722
|
+
import { defineRule as defineRule15 } from "@oxlint/plugins";
|
|
1883
1723
|
var DEFAULT_SAFETY_MARKERS = ["SAFETY"];
|
|
1884
1724
|
var commentOwnerKinds = new Set([
|
|
1885
1725
|
"ExpressionStatement",
|
|
@@ -1922,7 +1762,7 @@ function hasSafetyComment(sourceCode, node, pattern) {
|
|
|
1922
1762
|
current = current.parent;
|
|
1923
1763
|
}
|
|
1924
1764
|
}
|
|
1925
|
-
var requireSafetyCommentForTypeAssertionRule =
|
|
1765
|
+
var requireSafetyCommentForTypeAssertionRule = defineRule15({
|
|
1926
1766
|
meta: {
|
|
1927
1767
|
type: "problem",
|
|
1928
1768
|
docs: {
|
|
@@ -1972,7 +1812,7 @@ var requireSafetyCommentForTypeAssertionRule = defineRule17({
|
|
|
1972
1812
|
});
|
|
1973
1813
|
|
|
1974
1814
|
// vendor/anti-slop/src/index.ts
|
|
1975
|
-
var antiSlopPlugin =
|
|
1815
|
+
var antiSlopPlugin = eslintCompatPlugin({
|
|
1976
1816
|
meta: { name: "anti-slop" },
|
|
1977
1817
|
rules: {
|
|
1978
1818
|
"no-chained-type-assertions": noChainedTypeAssertionsRule,
|
|
@@ -1994,11 +1834,11 @@ var antiSlopPlugin = eslintCompatPlugin3({
|
|
|
1994
1834
|
});
|
|
1995
1835
|
var src_default = antiSlopPlugin;
|
|
1996
1836
|
// src/generic/index.ts
|
|
1997
|
-
import { eslintCompatPlugin as
|
|
1837
|
+
import { eslintCompatPlugin as eslintCompatPlugin2 } from "@oxlint/plugins";
|
|
1998
1838
|
|
|
1999
1839
|
// src/generic/rules/prefer-event-parameter-type.ts
|
|
2000
|
-
import { defineRule as
|
|
2001
|
-
function
|
|
1840
|
+
import { defineRule as defineRule16 } from "@oxlint/plugins";
|
|
1841
|
+
function nearestEnclosingFunction(node) {
|
|
2002
1842
|
let current = node.parent;
|
|
2003
1843
|
while (current) {
|
|
2004
1844
|
if (current.type === "FunctionDeclaration" || current.type === "FunctionExpression" || current.type === "ArrowFunctionExpression") {
|
|
@@ -2015,7 +1855,7 @@ function assertedEventParameter(node) {
|
|
|
2015
1855
|
}
|
|
2016
1856
|
const parameterName = expression.object.name;
|
|
2017
1857
|
const property = expression.property.name;
|
|
2018
|
-
const owner =
|
|
1858
|
+
const owner = nearestEnclosingFunction(node);
|
|
2019
1859
|
if (!owner?.params.some((parameter) => parameter.type === "Identifier" && parameter.name === parameterName)) {
|
|
2020
1860
|
return null;
|
|
2021
1861
|
}
|
|
@@ -2024,7 +1864,7 @@ function assertedEventParameter(node) {
|
|
|
2024
1864
|
property
|
|
2025
1865
|
};
|
|
2026
1866
|
}
|
|
2027
|
-
var preferEventParameterTypeRule =
|
|
1867
|
+
var preferEventParameterTypeRule = defineRule16({
|
|
2028
1868
|
meta: {
|
|
2029
1869
|
type: "suggestion",
|
|
2030
1870
|
docs: {
|
|
@@ -2053,7 +1893,7 @@ var preferEventParameterTypeRule = defineRule18({
|
|
|
2053
1893
|
});
|
|
2054
1894
|
|
|
2055
1895
|
// src/generic/index.ts
|
|
2056
|
-
var timmoPlugin =
|
|
1896
|
+
var timmoPlugin = eslintCompatPlugin2({
|
|
2057
1897
|
meta: { name: "timmo" },
|
|
2058
1898
|
rules: {
|
|
2059
1899
|
"prefer-event-parameter-type": preferEventParameterTypeRule
|
|
@@ -2087,8 +1927,168 @@ var recommended = defineConfig({
|
|
|
2087
1927
|
});
|
|
2088
1928
|
var recommended_default = recommended;
|
|
2089
1929
|
|
|
2090
|
-
// src/
|
|
2091
|
-
|
|
1930
|
+
// src/effect/index.ts
|
|
1931
|
+
import { eslintCompatPlugin as eslintCompatPlugin3 } from "@oxlint/plugins";
|
|
1932
|
+
|
|
1933
|
+
// src/effect/rules/no-try-catch-in-effect-generators.ts
|
|
1934
|
+
import { defineRule as defineRule17 } from "@oxlint/plugins";
|
|
1935
|
+
function resolveVariable4(sourceCode, identifier) {
|
|
1936
|
+
let scope = sourceCode.getScope(identifier);
|
|
1937
|
+
while (scope) {
|
|
1938
|
+
const variable = scope.set.get(identifier.name);
|
|
1939
|
+
if (variable)
|
|
1940
|
+
return variable;
|
|
1941
|
+
scope = scope.upper;
|
|
1942
|
+
}
|
|
1943
|
+
return null;
|
|
1944
|
+
}
|
|
1945
|
+
function nearestEnclosingFunction2(node) {
|
|
1946
|
+
let current = node.parent;
|
|
1947
|
+
while (current) {
|
|
1948
|
+
if (current.type === "FunctionDeclaration" || current.type === "FunctionExpression" || current.type === "ArrowFunctionExpression") {
|
|
1949
|
+
return current;
|
|
1950
|
+
}
|
|
1951
|
+
current = current.parent;
|
|
1952
|
+
}
|
|
1953
|
+
return null;
|
|
1954
|
+
}
|
|
1955
|
+
function staticMemberName(node) {
|
|
1956
|
+
if (node.type !== "MemberExpression" || node.computed)
|
|
1957
|
+
return null;
|
|
1958
|
+
return node.property.type === "Identifier" ? node.property.name : null;
|
|
1959
|
+
}
|
|
1960
|
+
function isEffectImport(sourceCode, identifier, namespace) {
|
|
1961
|
+
const variable = resolveVariable4(sourceCode, identifier);
|
|
1962
|
+
return variable?.defs.some((definition) => {
|
|
1963
|
+
if (definition.type !== "ImportBinding" || definition.parent?.type !== "ImportDeclaration" || definition.parent.source.value !== "effect") {
|
|
1964
|
+
return false;
|
|
1965
|
+
}
|
|
1966
|
+
if (namespace)
|
|
1967
|
+
return definition.node.type === "ImportNamespaceSpecifier";
|
|
1968
|
+
if (definition.node.type !== "ImportSpecifier")
|
|
1969
|
+
return false;
|
|
1970
|
+
const imported = definition.node.imported;
|
|
1971
|
+
return (imported.type === "Identifier" ? imported.name : imported.value) === "Effect";
|
|
1972
|
+
}) ?? false;
|
|
1973
|
+
}
|
|
1974
|
+
function isEffectMethod(sourceCode, node, method) {
|
|
1975
|
+
if (staticMemberName(node) !== method || node.type !== "MemberExpression") {
|
|
1976
|
+
return false;
|
|
1977
|
+
}
|
|
1978
|
+
const object = node.object;
|
|
1979
|
+
if (object.type === "Identifier") {
|
|
1980
|
+
return isEffectImport(sourceCode, object, false);
|
|
1981
|
+
}
|
|
1982
|
+
if (staticMemberName(object) !== "Effect" || object.type !== "MemberExpression" || object.object.type !== "Identifier") {
|
|
1983
|
+
return false;
|
|
1984
|
+
}
|
|
1985
|
+
return isEffectImport(sourceCode, object.object, true);
|
|
1986
|
+
}
|
|
1987
|
+
function isDirectArgument(owner, call) {
|
|
1988
|
+
return call.arguments.some((argument) => argument === owner);
|
|
1989
|
+
}
|
|
1990
|
+
function isRecognisedEffectGenerator(sourceCode, owner) {
|
|
1991
|
+
const parent = owner.parent;
|
|
1992
|
+
if (parent.type !== "CallExpression" || !isDirectArgument(owner, parent)) {
|
|
1993
|
+
return false;
|
|
1994
|
+
}
|
|
1995
|
+
if (isEffectMethod(sourceCode, parent.callee, "gen"))
|
|
1996
|
+
return true;
|
|
1997
|
+
const factoryCall = parent.callee;
|
|
1998
|
+
return factoryCall.type === "CallExpression" && isEffectMethod(sourceCode, factoryCall.callee, "fn");
|
|
1999
|
+
}
|
|
2000
|
+
var noTryCatchInEffectGeneratorsRule = defineRule17({
|
|
2001
|
+
meta: {
|
|
2002
|
+
type: "problem",
|
|
2003
|
+
docs: {
|
|
2004
|
+
description: "Disallow synchronous try/catch owned by recognised Effect generator callbacks."
|
|
2005
|
+
},
|
|
2006
|
+
messages: {
|
|
2007
|
+
useEffectErrorChannel: "Keep expected failures in the Effect error channel. Use Effect.try for synchronous throwing work, Effect.tryPromise for asynchronous throwing work, Effect-returning schema APIs for decoding, and Effect recovery combinators for recovery."
|
|
2008
|
+
}
|
|
2009
|
+
},
|
|
2010
|
+
create(context) {
|
|
2011
|
+
return {
|
|
2012
|
+
TryStatement(node) {
|
|
2013
|
+
if (!node.handler)
|
|
2014
|
+
return;
|
|
2015
|
+
const owner = nearestEnclosingFunction2(node);
|
|
2016
|
+
if (!owner?.generator || !isRecognisedEffectGenerator(context.sourceCode, owner)) {
|
|
2017
|
+
return;
|
|
2018
|
+
}
|
|
2019
|
+
context.report({ node, messageId: "useEffectErrorChannel" });
|
|
2020
|
+
}
|
|
2021
|
+
};
|
|
2022
|
+
}
|
|
2023
|
+
});
|
|
2024
|
+
|
|
2025
|
+
// src/effect/index.ts
|
|
2026
|
+
var timmoEffectPlugin = eslintCompatPlugin3({
|
|
2027
|
+
meta: { name: "timmo-effect" },
|
|
2028
|
+
rules: {
|
|
2029
|
+
"no-try-catch-in-effect-generators": noTryCatchInEffectGeneratorsRule
|
|
2030
|
+
}
|
|
2031
|
+
});
|
|
2032
|
+
var effect_default = timmoEffectPlugin;
|
|
2033
|
+
|
|
2034
|
+
// vendor/anti-slop/src/effect/index.ts
|
|
2035
|
+
import { eslintCompatPlugin as eslintCompatPlugin4 } from "@oxlint/plugins";
|
|
2036
|
+
|
|
2037
|
+
// vendor/anti-slop/src/effect/rules/no-service-constructor-imports.ts
|
|
2038
|
+
import { defineRule as defineRule18 } from "@oxlint/plugins";
|
|
2039
|
+
var SERVICE_CONSTRUCTOR_NAME = /^make[A-Z]/u;
|
|
2040
|
+
var TEST_FILE = /\.(?:test|spec)\.[cm]?[jt]sx?$/u;
|
|
2041
|
+
function isProjectLocalImport(source) {
|
|
2042
|
+
return source.startsWith("./") || source.startsWith("../");
|
|
2043
|
+
}
|
|
2044
|
+
function getImportedName(specifier) {
|
|
2045
|
+
if (specifier.imported.type === "Identifier")
|
|
2046
|
+
return specifier.imported.name;
|
|
2047
|
+
return specifier.imported.value;
|
|
2048
|
+
}
|
|
2049
|
+
var noServiceConstructorImportsRule = defineRule18({
|
|
2050
|
+
meta: {
|
|
2051
|
+
type: "problem",
|
|
2052
|
+
docs: {
|
|
2053
|
+
description: "Disallow project-local make<CapabilityName> imports outside test and spec files."
|
|
2054
|
+
},
|
|
2055
|
+
messages: {
|
|
2056
|
+
serviceConstructorImport: 'Do not import Effect service constructor "{{name}}" into runtime code. Import the owning Layer, yield the contextual service, and allow its requirements to propagate to the composition root.'
|
|
2057
|
+
}
|
|
2058
|
+
},
|
|
2059
|
+
create(context) {
|
|
2060
|
+
const isTestFile = TEST_FILE.test(context.filename.replaceAll("\\", "/"));
|
|
2061
|
+
return {
|
|
2062
|
+
ImportDeclaration(node) {
|
|
2063
|
+
if (isTestFile || !isProjectLocalImport(node.source.value))
|
|
2064
|
+
return;
|
|
2065
|
+
for (const specifier of node.specifiers) {
|
|
2066
|
+
if (specifier.type !== "ImportSpecifier")
|
|
2067
|
+
continue;
|
|
2068
|
+
const importedName2 = getImportedName(specifier);
|
|
2069
|
+
if (!SERVICE_CONSTRUCTOR_NAME.test(importedName2))
|
|
2070
|
+
continue;
|
|
2071
|
+
context.report({
|
|
2072
|
+
node: specifier,
|
|
2073
|
+
messageId: "serviceConstructorImport",
|
|
2074
|
+
data: { name: importedName2 }
|
|
2075
|
+
});
|
|
2076
|
+
}
|
|
2077
|
+
}
|
|
2078
|
+
};
|
|
2079
|
+
}
|
|
2080
|
+
});
|
|
2081
|
+
|
|
2082
|
+
// vendor/anti-slop/src/effect/index.ts
|
|
2083
|
+
var antiSlopEffectPlugin = eslintCompatPlugin4({
|
|
2084
|
+
meta: { name: "anti-slop-effect" },
|
|
2085
|
+
rules: {
|
|
2086
|
+
"no-service-constructor-imports": noServiceConstructorImportsRule
|
|
2087
|
+
}
|
|
2088
|
+
});
|
|
2089
|
+
var effect_default2 = antiSlopEffectPlugin;
|
|
2090
|
+
// src/configs/recommended-effect.ts
|
|
2091
|
+
var recommendedEffect = defineConfig({
|
|
2092
2092
|
extends: [recommended_default],
|
|
2093
2093
|
jsPlugins: [
|
|
2094
2094
|
{
|
|
@@ -2102,7 +2102,7 @@ var effect = defineConfig({
|
|
|
2102
2102
|
...enablePluginRules("timmo-effect", effect_default)
|
|
2103
2103
|
}
|
|
2104
2104
|
});
|
|
2105
|
-
var
|
|
2105
|
+
var recommended_effect_default = recommendedEffect;
|
|
2106
2106
|
export {
|
|
2107
|
-
|
|
2107
|
+
recommended_effect_default as default
|
|
2108
2108
|
};
|