@timmo001/oxlint-rules 0.3.0 → 0.3.2

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 (28) hide show
  1. package/README.md +2 -1
  2. package/THIRD_PARTY_NOTICES.md +9 -0
  3. package/dist/cli.js +978 -83
  4. package/dist/configs/recommended-effect.js +1207 -312
  5. package/dist/configs/recommended.js +772 -70
  6. package/dist/upstream/anti-slop.js +765 -63
  7. package/dist/upstream/effect.js +196 -3
  8. package/package.json +5 -5
  9. package/vendor/anti-slop/src/effect/index.ts +8 -0
  10. package/vendor/anti-slop/src/effect/rules/no-manual-effect-error-tag.ts +52 -0
  11. package/vendor/anti-slop/src/effect/rules/no-manual-tag-comparison.ts +45 -0
  12. package/vendor/anti-slop/src/effect/rules/no-manual-tagged-construction.ts +37 -0
  13. package/vendor/anti-slop/src/effect/rules/prefer-effect-match.ts +54 -0
  14. package/vendor/anti-slop/src/effect/shared/tagged-values.ts +97 -0
  15. package/vendor/anti-slop/src/index.ts +6 -0
  16. package/vendor/anti-slop/src/rules/no-array-filter-map.ts +28 -0
  17. package/vendor/anti-slop/src/rules/no-known-value-widening.ts +2 -14
  18. package/vendor/anti-slop/src/rules/no-module-mocking.ts +3 -14
  19. package/vendor/anti-slop/src/rules/no-reduce-accumulator-copy.ts +109 -0
  20. package/vendor/anti-slop/src/rules/require-readable-spacing.ts +47 -0
  21. package/vendor/anti-slop/src/shared/array-method.ts +94 -0
  22. package/vendor/anti-slop/src/shared/reflect-method.ts +2 -13
  23. package/vendor/anti-slop/src/shared/scope.ts +15 -0
  24. package/vendor/anti-slop/src/vendor/eslint-stylistic/LICENSE +22 -0
  25. package/vendor/anti-slop/src/vendor/eslint-stylistic/UPSTREAM.md +28 -0
  26. package/vendor/anti-slop/src/vendor/eslint-stylistic/padding-line-ast.ts +51 -0
  27. package/vendor/anti-slop/src/vendor/eslint-stylistic/padding-line-between-statements.ts +906 -0
  28. package/vendor/anti-slop/src/vendor/eslint-stylistic/padding-line-options.d.ts +87 -0
package/dist/cli.js CHANGED
@@ -1,10 +1,213 @@
1
1
  #!/usr/bin/env node
2
2
 
3
+ // src/cli.ts
4
+ import { resolve as resolve2 } from "node:path";
5
+
6
+ // node_modules/oxlint/dist/index.js
7
+ function defineConfig(config) {
8
+ return config;
9
+ }
10
+
3
11
  // vendor/anti-slop/src/index.ts
4
12
  import { eslintCompatPlugin } from "@oxlint/plugins";
5
13
 
6
- // vendor/anti-slop/src/rules/no-chained-type-assertions.ts
14
+ // vendor/anti-slop/src/rules/no-array-filter-map.ts
7
15
  import { defineRule } from "@oxlint/plugins";
16
+
17
+ // vendor/anti-slop/src/shared/array-method.ts
18
+ function unwrapArrayExpression(node) {
19
+ while (node.type === "ParenthesizedExpression" || node.type === "ChainExpression" || node.type === "TSAsExpression" || node.type === "TSTypeAssertion" || node.type === "TSNonNullExpression" || node.type === "TSSatisfiesExpression") {
20
+ node = node.expression;
21
+ }
22
+ return node;
23
+ }
24
+ function resolveArrayBinding(sourceCode, node) {
25
+ node = unwrapArrayExpression(node);
26
+ if (node.type !== "Identifier")
27
+ return null;
28
+ let scope = sourceCode.getScope(node);
29
+ while (scope !== null) {
30
+ const variable = scope.set.get(node.name);
31
+ if (variable !== undefined)
32
+ return variable;
33
+ scope = scope.upper;
34
+ }
35
+ return null;
36
+ }
37
+ function arrayMethodTarget(node) {
38
+ node = unwrapArrayExpression(node);
39
+ if (node.type !== "MemberExpression")
40
+ return null;
41
+ const property = node.property;
42
+ if (!node.computed && property.type === "Identifier") {
43
+ return { name: property.name, object: node.object };
44
+ }
45
+ if (node.computed && property.type === "Literal" && typeof property.value === "string") {
46
+ return { name: property.value, object: node.object };
47
+ }
48
+ return null;
49
+ }
50
+ function isArrayAnnotation(type) {
51
+ if (type.type === "TSArrayType" || type.type === "TSTupleType")
52
+ return true;
53
+ if (type.type === "TSParenthesizedType")
54
+ return isArrayAnnotation(type.typeAnnotation);
55
+ if (type.type === "TSTypeOperator" && type.operator === "readonly") {
56
+ return isArrayAnnotation(type.typeAnnotation);
57
+ }
58
+ return type.type === "TSTypeReference" && type.typeName.type === "Identifier" && (type.typeName.name === "Array" || type.typeName.name === "ReadonlyArray");
59
+ }
60
+ function isKnownArrayExpression(sourceCode, node, visited = new Set) {
61
+ node = unwrapArrayExpression(node);
62
+ if (node.type === "ArrayExpression")
63
+ return true;
64
+ if (node.type === "CallExpression") {
65
+ const method = arrayMethodTarget(node.callee);
66
+ return method !== null && ["map", "filter", "flatMap", "slice", "concat", "toSorted", "toReversed", "toSpliced"].includes(method.name) && isKnownArrayExpression(sourceCode, method.object, visited);
67
+ }
68
+ if (node.type !== "Identifier")
69
+ return false;
70
+ const variable = resolveArrayBinding(sourceCode, node);
71
+ if (variable === null || visited.has(variable))
72
+ return false;
73
+ visited.add(variable);
74
+ if (variable.references.some((reference) => reference.isWrite() && !reference.init))
75
+ return false;
76
+ for (const identifier of variable.identifiers) {
77
+ const annotation = identifier.typeAnnotation?.typeAnnotation;
78
+ if (annotation !== undefined)
79
+ return isArrayAnnotation(annotation);
80
+ }
81
+ for (const definition of variable.defs) {
82
+ if (definition.type === "Variable" && definition.node.type === "VariableDeclarator" && definition.node.id.type === "Identifier" && definition.node.init !== null && definition.node.parent.type === "VariableDeclaration" && definition.node.parent.kind === "const") {
83
+ return isKnownArrayExpression(sourceCode, definition.node.init, visited);
84
+ }
85
+ }
86
+ return false;
87
+ }
88
+
89
+ // vendor/anti-slop/src/rules/no-array-filter-map.ts
90
+ var noArrayFilterMapRule = defineRule({
91
+ meta: {
92
+ type: "suggestion",
93
+ docs: { description: "Disallow adjacent array filter/map passes in favor of lazy iterator helpers or a single transformation." },
94
+ messages: {
95
+ arrayFilterMap: "Avoid consecutive array `{{first}}` and `{{second}}` passes. Prefer `.values().{{first}}(...).{{second}}(...).toArray()` where iterator helpers are supported, or a single `flatMap`/mutating reducer. Preserve callback ordering, indexes, and filtering semantics."
96
+ }
97
+ },
98
+ createOnce(context) {
99
+ return {
100
+ CallExpression(node) {
101
+ const outer = arrayMethodTarget(node.callee);
102
+ if (outer === null || outer.name !== "map" && outer.name !== "filter")
103
+ return;
104
+ const innerCall = unwrapArrayExpression(outer.object);
105
+ if (innerCall.type !== "CallExpression")
106
+ return;
107
+ const inner = arrayMethodTarget(innerCall.callee);
108
+ if (inner === null || inner.name !== (outer.name === "map" ? "filter" : "map"))
109
+ return;
110
+ if (!isKnownArrayExpression(context.sourceCode, inner.object))
111
+ return;
112
+ context.report({ node, messageId: "arrayFilterMap", data: { first: inner.name, second: outer.name } });
113
+ }
114
+ };
115
+ }
116
+ });
117
+
118
+ // vendor/anti-slop/src/rules/no-reduce-accumulator-copy.ts
119
+ import { defineRule as defineRule2 } from "@oxlint/plugins";
120
+ function enclosingReducer(node) {
121
+ let parent = node.parent;
122
+ while (parent !== null) {
123
+ if (parent.type === "FunctionDeclaration")
124
+ return null;
125
+ if (parent.type === "ArrowFunctionExpression" || parent.type === "FunctionExpression") {
126
+ const callback = parent;
127
+ let owner = callback.parent;
128
+ while (owner !== null && unwrapArrayExpression(owner) === callback)
129
+ owner = owner.parent;
130
+ if (owner?.type !== "CallExpression")
131
+ return null;
132
+ const method = arrayMethodTarget(owner.callee);
133
+ const firstArgument = owner.arguments[0];
134
+ if (method === null || method.name !== "reduce" && method.name !== "reduceRight" || owner.arguments.length > 2 || firstArgument === undefined || unwrapArrayExpression(firstArgument) !== callback)
135
+ return null;
136
+ const firstParameter = callback.params[0];
137
+ const accumulator = firstParameter?.type === "AssignmentPattern" ? firstParameter.left : firstParameter;
138
+ if (accumulator?.type !== "Identifier")
139
+ return null;
140
+ return { callback, accumulator, initialValue: owner.arguments[1] };
141
+ }
142
+ parent = parent.parent;
143
+ }
144
+ return null;
145
+ }
146
+ function referencesAccumulator(sourceCode, node, accumulator, visited = new Set) {
147
+ const variable = resolveArrayBinding(sourceCode, node);
148
+ if (variable === null || visited.has(variable))
149
+ return false;
150
+ if (variable === accumulator)
151
+ return true;
152
+ visited.add(variable);
153
+ if (variable.references.some((reference) => reference.isWrite() && !reference.init))
154
+ return false;
155
+ for (const definition of variable.defs) {
156
+ if (definition.type === "Variable" && definition.node.type === "VariableDeclarator" && definition.node.id.type === "Identifier" && definition.node.init !== null && definition.node.parent.type === "VariableDeclaration" && definition.node.parent.kind === "const") {
157
+ return referencesAccumulator(sourceCode, definition.node.init, accumulator, visited);
158
+ }
159
+ }
160
+ return false;
161
+ }
162
+ function isGlobalCopyOwner(sourceCode, node, name) {
163
+ node = unwrapArrayExpression(node);
164
+ if (node.type !== "Identifier" || node.name !== name)
165
+ return false;
166
+ const variable = resolveArrayBinding(sourceCode, node);
167
+ return variable === null || variable.defs.length === 0;
168
+ }
169
+ var noReduceAccumulatorCopyRule = defineRule2({
170
+ meta: {
171
+ type: "problem",
172
+ docs: { description: "Disallow copying growing reducer accumulators with Object.assign, Array.from, or array copy methods." },
173
+ messages: {
174
+ accumulatorCopy: "Do not copy the reducer accumulator on every iteration; growing copies can cause quadratic work. Mutate a fresh, locally owned accumulator and return it, or use an iterator pipeline/flatMap."
175
+ }
176
+ },
177
+ createOnce(context) {
178
+ return {
179
+ CallExpression(node) {
180
+ const method = arrayMethodTarget(node.callee);
181
+ if (method === null)
182
+ return;
183
+ const reducer = enclosingReducer(node);
184
+ if (reducer === null)
185
+ return;
186
+ const accumulator = context.sourceCode.getDeclaredVariables(reducer.callback).find((variable) => variable.identifiers.some((identifier) => identifier.start === reducer.accumulator.start));
187
+ if (accumulator === undefined)
188
+ return;
189
+ const isAccumulator = (expression) => referencesAccumulator(context.sourceCode, expression, accumulator);
190
+ let copiesAccumulator = false;
191
+ if (method.name === "assign" && isGlobalCopyOwner(context.sourceCode, method.object, "Object")) {
192
+ const target = node.arguments[0];
193
+ copiesAccumulator = target !== undefined && unwrapArrayExpression(target).type === "ObjectExpression" && node.arguments.slice(1).some(isAccumulator);
194
+ } else if (method.name === "from" && isGlobalCopyOwner(context.sourceCode, method.object, "Array")) {
195
+ const source = node.arguments[0];
196
+ copiesAccumulator = source !== undefined && isAccumulator(source);
197
+ } else if (["concat", "slice", "toSpliced", "toSorted", "toReversed", "with"].includes(method.name)) {
198
+ const initialValue = reducer.initialValue;
199
+ const arrayAccumulator = initialValue !== undefined && isKnownArrayExpression(context.sourceCode, initialValue);
200
+ copiesAccumulator = arrayAccumulator && isAccumulator(method.object);
201
+ }
202
+ if (copiesAccumulator)
203
+ context.report({ node, messageId: "accumulatorCopy" });
204
+ }
205
+ };
206
+ }
207
+ });
208
+
209
+ // vendor/anti-slop/src/rules/no-chained-type-assertions.ts
210
+ import { defineRule as defineRule3 } from "@oxlint/plugins";
8
211
  function isTypeAssertionExpression(node) {
9
212
  return node.type === "TSAsExpression" || node.type === "TSTypeAssertion";
10
213
  }
@@ -39,7 +242,7 @@ function isForbiddenAssertionChain(node) {
39
242
  }
40
243
  return assertionCount > 1 && hasNonConstAssertion;
41
244
  }
42
- var noChainedTypeAssertionsRule = defineRule({
245
+ var noChainedTypeAssertionsRule = defineRule3({
43
246
  meta: {
44
247
  type: "problem",
45
248
  docs: {
@@ -63,7 +266,7 @@ var noChainedTypeAssertionsRule = defineRule({
63
266
  });
64
267
 
65
268
  // vendor/anti-slop/src/rules/no-conditional-empty-object-spread.ts
66
- import { defineRule as defineRule2 } from "@oxlint/plugins";
269
+ import { defineRule as defineRule4 } from "@oxlint/plugins";
67
270
  function unwrapParentheses(node) {
68
271
  let current = node;
69
272
  while (current.type === "ParenthesizedExpression") {
@@ -78,7 +281,7 @@ function isConditionalEmptyObjectSpread(node) {
78
281
  const conditional = unwrapParentheses(node);
79
282
  return conditional.type === "ConditionalExpression" && (isEmptyObjectExpression(conditional.consequent) || isEmptyObjectExpression(conditional.alternate));
80
283
  }
81
- var noConditionalEmptyObjectSpreadRule = defineRule2({
284
+ var noConditionalEmptyObjectSpreadRule = defineRule4({
82
285
  meta: {
83
286
  type: "suggestion",
84
287
  docs: {
@@ -102,7 +305,7 @@ var noConditionalEmptyObjectSpreadRule = defineRule2({
102
305
  });
103
306
 
104
307
  // vendor/anti-slop/src/rules/no-known-value-widening.ts
105
- import { defineRule as defineRule3 } from "@oxlint/plugins";
308
+ import { defineRule as defineRule5 } from "@oxlint/plugins";
106
309
 
107
310
  // vendor/anti-slop/src/shared/lexical-type-parameters.ts
108
311
  function isNode(value) {
@@ -505,9 +708,9 @@ function classifyWideningTarget(type, environment) {
505
708
  if (alias === null)
506
709
  return null;
507
710
  if ((alias.typeParameters?.params.length ?? 0) > 0) {
508
- const substitutions2 = aliasSubstitution(alias, unwrapped, new Map);
509
- const resolved2 = substitutions2 === null ? null : classifyAliasBroadTarget(alias.typeAnnotation, environment, substitutions2, new Set([name]));
510
- return resolved2?.kind === "open dictionary" ? { kind: "generic container" } : null;
711
+ const substitutions = aliasSubstitution(alias, unwrapped, new Map);
712
+ const resolved = substitutions === null ? null : classifyAliasBroadTarget(alias.typeAnnotation, environment, substitutions, new Set([name]));
713
+ return resolved?.kind === "open dictionary" ? { kind: "generic container" } : null;
511
714
  }
512
715
  const substitutions = aliasSubstitution(alias, unwrapped, new Map);
513
716
  if (substitutions === null)
@@ -631,14 +834,7 @@ function functionParameterBindingName(parameter, sourceCode) {
631
834
  return annotationStart === undefined ? sourceText : sourceText.slice(0, annotationStart - parameter.start).trimEnd();
632
835
  }
633
836
 
634
- // vendor/anti-slop/src/rules/no-known-value-widening.ts
635
- function unwrapExpression(expression) {
636
- let current = expression;
637
- while (current.type === "ParenthesizedExpression" || current.type === "TSAsExpression" || current.type === "TSSatisfiesExpression" || current.type === "TSTypeAssertion" || current.type === "TSNonNullExpression") {
638
- current = current.expression;
639
- }
640
- return current;
641
- }
837
+ // vendor/anti-slop/src/shared/scope.ts
642
838
  function resolveVariable(sourceCode, identifier) {
643
839
  let scope = sourceCode.getScope(identifier);
644
840
  while (scope !== null) {
@@ -649,6 +845,15 @@ function resolveVariable(sourceCode, identifier) {
649
845
  }
650
846
  return null;
651
847
  }
848
+
849
+ // vendor/anti-slop/src/rules/no-known-value-widening.ts
850
+ function unwrapExpression(expression) {
851
+ let current = expression;
852
+ while (current.type === "ParenthesizedExpression" || current.type === "TSAsExpression" || current.type === "TSSatisfiesExpression" || current.type === "TSTypeAssertion" || current.type === "TSNonNullExpression") {
853
+ current = current.expression;
854
+ }
855
+ return current;
856
+ }
652
857
  function variableDeclarator(variable) {
653
858
  if (variable.defs.length !== 1)
654
859
  return null;
@@ -801,7 +1006,7 @@ function isDictionaryAccumulatorTarget(destination) {
801
1006
  function hasParentAssertion(node) {
802
1007
  return node.parent?.type === "TSAsExpression" || node.parent?.type === "TSTypeAssertion";
803
1008
  }
804
- var noKnownValueWideningRule = defineRule3({
1009
+ var noKnownValueWideningRule = defineRule5({
805
1010
  meta: {
806
1011
  type: "problem",
807
1012
  docs: {
@@ -914,18 +1119,8 @@ var noKnownValueWideningRule = defineRule3({
914
1119
  });
915
1120
 
916
1121
  // vendor/anti-slop/src/rules/no-module-mocking.ts
917
- import { defineRule as defineRule4 } from "@oxlint/plugins";
1122
+ import { defineRule as defineRule6 } from "@oxlint/plugins";
918
1123
  var moduleMockMethods = new Set(["doMock", "mock", "unstable_mockModule"]);
919
- function resolveVariable2(sourceCode, identifier) {
920
- let scope = sourceCode.getScope(identifier);
921
- while (scope !== null) {
922
- const variable = scope.set.get(identifier.name);
923
- if (variable !== undefined)
924
- return variable;
925
- scope = scope.upper;
926
- }
927
- return null;
928
- }
929
1124
  function importedName(node) {
930
1125
  if (node.type !== "ImportSpecifier")
931
1126
  return null;
@@ -937,7 +1132,7 @@ function isTestFrameworkObject(sourceCode, expression) {
937
1132
  if ((expression.name === "vi" || expression.name === "jest") && sourceCode.isGlobalReference(expression)) {
938
1133
  return true;
939
1134
  }
940
- const variable = resolveVariable2(sourceCode, expression);
1135
+ const variable = resolveVariable(sourceCode, expression);
941
1136
  if (variable === null || variable.defs.length === 0) {
942
1137
  return expression.name === "vi" || expression.name === "jest";
943
1138
  }
@@ -959,7 +1154,7 @@ function moduleMockCall(sourceCode, callee) {
959
1154
  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;
960
1155
  return method !== null && moduleMockMethods.has(method);
961
1156
  }
962
- var noModuleMockingRule = defineRule4({
1157
+ var noModuleMockingRule = defineRule6({
963
1158
  meta: {
964
1159
  type: "problem",
965
1160
  docs: {
@@ -983,8 +1178,8 @@ var noModuleMockingRule = defineRule4({
983
1178
  });
984
1179
 
985
1180
  // vendor/anti-slop/src/rules/no-object-parameters.ts
986
- import { defineRule as defineRule5 } from "@oxlint/plugins";
987
- var noObjectParametersRule = defineRule5({
1181
+ import { defineRule as defineRule7 } from "@oxlint/plugins";
1182
+ var noObjectParametersRule = defineRule7({
988
1183
  meta: {
989
1184
  type: "problem",
990
1185
  docs: {
@@ -1037,25 +1232,15 @@ var noObjectParametersRule = defineRule5({
1037
1232
  });
1038
1233
 
1039
1234
  // vendor/anti-slop/src/rules/no-reflect-apply.ts
1040
- import { defineRule as defineRule6 } from "@oxlint/plugins";
1235
+ import { defineRule as defineRule8 } from "@oxlint/plugins";
1041
1236
 
1042
1237
  // vendor/anti-slop/src/shared/reflect-method.ts
1043
- function resolveVariable3(sourceCode, identifier) {
1044
- let scope = sourceCode.getScope(identifier);
1045
- while (scope !== null) {
1046
- const variable = scope.set.get(identifier.name);
1047
- if (variable !== undefined)
1048
- return variable;
1049
- scope = scope.upper;
1050
- }
1051
- return null;
1052
- }
1053
1238
  function isGlobalReflect(sourceCode, expression) {
1054
1239
  if (expression.type !== "Identifier" || expression.name !== "Reflect")
1055
1240
  return false;
1056
1241
  if (sourceCode.isGlobalReference(expression))
1057
1242
  return true;
1058
- const variable = resolveVariable3(sourceCode, expression);
1243
+ const variable = resolveVariable(sourceCode, expression);
1059
1244
  return variable === null || variable.defs.length === 0;
1060
1245
  }
1061
1246
  function isGlobalReflectMethodCall(sourceCode, callee, methodName) {
@@ -1068,7 +1253,7 @@ function isGlobalReflectMethodCall(sourceCode, callee, methodName) {
1068
1253
  }
1069
1254
 
1070
1255
  // vendor/anti-slop/src/rules/no-reflect-apply.ts
1071
- var noReflectApplyRule = defineRule6({
1256
+ var noReflectApplyRule = defineRule8({
1072
1257
  meta: {
1073
1258
  type: "problem",
1074
1259
  docs: {
@@ -1092,8 +1277,8 @@ var noReflectApplyRule = defineRule6({
1092
1277
  });
1093
1278
 
1094
1279
  // vendor/anti-slop/src/rules/no-reflect-get.ts
1095
- import { defineRule as defineRule7 } from "@oxlint/plugins";
1096
- var noReflectGetRule = defineRule7({
1280
+ import { defineRule as defineRule9 } from "@oxlint/plugins";
1281
+ var noReflectGetRule = defineRule9({
1097
1282
  meta: {
1098
1283
  type: "problem",
1099
1284
  docs: {
@@ -1117,7 +1302,7 @@ var noReflectGetRule = defineRule7({
1117
1302
  });
1118
1303
 
1119
1304
  // vendor/anti-slop/src/rules/no-runtime-typeof.ts
1120
- import { defineRule as defineRule8 } from "@oxlint/plugins";
1305
+ import { defineRule as defineRule10 } from "@oxlint/plugins";
1121
1306
  function isRuntimeFunction(node) {
1122
1307
  return node.type === "ArrowFunctionExpression" || node.type === "FunctionDeclaration" || node.type === "FunctionExpression";
1123
1308
  }
@@ -1140,7 +1325,7 @@ function isExistenceProbe(node) {
1140
1325
  const other = parent.left === node ? parent.right : parent.left;
1141
1326
  return other.type === "Literal" && other.value === "undefined";
1142
1327
  }
1143
- var noRuntimeTypeofRule = defineRule8({
1328
+ var noRuntimeTypeofRule = defineRule10({
1144
1329
  meta: {
1145
1330
  type: "problem",
1146
1331
  docs: {
@@ -1174,7 +1359,7 @@ var noRuntimeTypeofRule = defineRule8({
1174
1359
  });
1175
1360
 
1176
1361
  // vendor/anti-slop/src/rules/no-shape-in-symbol-names.ts
1177
- import { defineRule as defineRule9 } from "@oxlint/plugins";
1362
+ import { defineRule as defineRule11 } from "@oxlint/plugins";
1178
1363
  var FORBIDDEN_SYMBOL_NAME = "shape";
1179
1364
  function containsForbiddenSymbolName(name) {
1180
1365
  return name.toLowerCase().includes(FORBIDDEN_SYMBOL_NAME);
@@ -1185,7 +1370,7 @@ function isBorrowedMemberName(node) {
1185
1370
  return false;
1186
1371
  return parent.property === node && parent.computed === false;
1187
1372
  }
1188
- var noForbiddenTermInSymbolNamesRule = defineRule9({
1373
+ var noForbiddenTermInSymbolNamesRule = defineRule11({
1189
1374
  meta: {
1190
1375
  type: "problem",
1191
1376
  docs: {
@@ -1214,12 +1399,12 @@ var noForbiddenTermInSymbolNamesRule = defineRule9({
1214
1399
  });
1215
1400
 
1216
1401
  // vendor/anti-slop/src/rules/no-unknown-parameters.ts
1217
- import { defineRule as defineRule10 } from "@oxlint/plugins";
1402
+ import { defineRule as defineRule12 } from "@oxlint/plugins";
1218
1403
  function isTypePredicateSubject(owner, parameterName) {
1219
1404
  const predicate = owner.returnType?.typeAnnotation;
1220
1405
  return predicate?.type === "TSTypePredicate" && predicate.parameterName.type === "Identifier" && predicate.parameterName.name === parameterName;
1221
1406
  }
1222
- var noUnknownParametersRule = defineRule10({
1407
+ var noUnknownParametersRule = defineRule12({
1223
1408
  meta: {
1224
1409
  type: "problem",
1225
1410
  docs: {
@@ -1263,8 +1448,8 @@ var noUnknownParametersRule = defineRule10({
1263
1448
  });
1264
1449
 
1265
1450
  // vendor/anti-slop/src/rules/no-unknown-returns.ts
1266
- import { defineRule as defineRule11 } from "@oxlint/plugins";
1267
- var noUnknownReturnsRule = defineRule11({
1451
+ import { defineRule as defineRule13 } from "@oxlint/plugins";
1452
+ var noUnknownReturnsRule = defineRule13({
1268
1453
  meta: {
1269
1454
  type: "problem",
1270
1455
  docs: {
@@ -1317,8 +1502,8 @@ var noUnknownReturnsRule = defineRule11({
1317
1502
  });
1318
1503
 
1319
1504
  // vendor/anti-slop/src/rules/no-unknown-type-aliases.ts
1320
- import { defineRule as defineRule12 } from "@oxlint/plugins";
1321
- var noUnknownTypeAliasesRule = defineRule12({
1505
+ import { defineRule as defineRule14 } from "@oxlint/plugins";
1506
+ var noUnknownTypeAliasesRule = defineRule14({
1322
1507
  meta: {
1323
1508
  type: "problem",
1324
1509
  docs: {
@@ -1356,7 +1541,7 @@ var noUnknownTypeAliasesRule = defineRule12({
1356
1541
  });
1357
1542
 
1358
1543
  // vendor/anti-slop/src/rules/no-unsafe-dictionary-type.ts
1359
- import { defineRule as defineRule13 } from "@oxlint/plugins";
1544
+ import { defineRule as defineRule15 } from "@oxlint/plugins";
1360
1545
  var typeNodeKinds = new Set([
1361
1546
  "JSDocNonNullableType",
1362
1547
  "JSDocNullableType",
@@ -1443,7 +1628,7 @@ function shouldReportType(node, environment) {
1443
1628
  }
1444
1629
  return true;
1445
1630
  }
1446
- var noUnsafeDictionaryTypeRule = defineRule13({
1631
+ var noUnsafeDictionaryTypeRule = defineRule15({
1447
1632
  meta: {
1448
1633
  type: "problem",
1449
1634
  docs: {
@@ -1485,7 +1670,7 @@ var noUnsafeDictionaryTypeRule = defineRule13({
1485
1670
  });
1486
1671
 
1487
1672
  // vendor/anti-slop/src/rules/no-widen-then-assert.ts
1488
- import { defineRule as defineRule14 } from "@oxlint/plugins";
1673
+ import { defineRule as defineRule16 } from "@oxlint/plugins";
1489
1674
  var functionBoundaryTypes = new Set([
1490
1675
  "ArrowFunctionExpression",
1491
1676
  "FunctionDeclaration",
@@ -1681,7 +1866,7 @@ function assertionIsNarrower(sourceText, broadKind, evidence, assertedType) {
1681
1866
  return isDefinitelyObjectType(assertedType);
1682
1867
  return isDefinitelyNarrowerRecordType(assertedType);
1683
1868
  }
1684
- var noWidenThenAssertRule = defineRule14({
1869
+ var noWidenThenAssertRule = defineRule16({
1685
1870
  meta: {
1686
1871
  type: "problem",
1687
1872
  docs: {
@@ -1720,8 +1905,530 @@ var noWidenThenAssertRule = defineRule14({
1720
1905
  }
1721
1906
  });
1722
1907
 
1908
+ // vendor/anti-slop/src/vendor/eslint-stylistic/padding-line-ast.ts
1909
+ var LINEBREAKS = new Set([`\r
1910
+ `, "\r", `
1911
+ `, "\u2028", "\u2029"]);
1912
+ var isClosingBraceToken = (token) => token.type === "Punctuator" && token.value === "}";
1913
+ var isSemicolonToken = (token) => token.type === "Punctuator" && token.value === ";";
1914
+ var isNotSemicolonToken = (token) => !isSemicolonToken(token);
1915
+ var isTokenOnSameLine = (left, right) => left.loc.end.line === right.loc.start.line;
1916
+ var isFunction = (node) => node.type === "FunctionDeclaration" || node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression";
1917
+ var isSingleLine = (node) => node.loc.start.line === node.loc.end.line;
1918
+ var skipChainExpression = (node) => node.type === "ChainExpression" ? node.expression : node;
1919
+ var isTopLevelExpressionStatement = (node) => node.type === "ExpressionStatement" && (node.parent.type === "Program" || node.parent.type === "BlockStatement" && isFunction(node.parent.parent));
1920
+ function isParenthesized(node, sourceCode) {
1921
+ const before = sourceCode.getTokenBefore(node);
1922
+ const after = sourceCode.getTokenAfter(node);
1923
+ return before?.value === "(" && after?.value === ")";
1924
+ }
1925
+
1926
+ // vendor/anti-slop/src/vendor/eslint-stylistic/padding-line-between-statements.ts
1927
+ var CJS_EXPORT = /^(?:module\s*\.\s*)?exports(?:\s*\.|\s*\[|$)/u;
1928
+ var CJS_IMPORT = /^require\(/u;
1929
+ var LT = `[${Array.from(LINEBREAKS).join("")}]`;
1930
+ var PADDING_LINE_SEQUENCE = new RegExp(String.raw`^(\s*?${LT})\s*${LT}(\s*;?)$`, "u");
1931
+ function isSelectorOption(option) {
1932
+ return typeof option === "object" && !Array.isArray(option);
1933
+ }
1934
+ function newKeywordTester(type, keyword) {
1935
+ return {
1936
+ test(node, sourceCode) {
1937
+ const isSameKeyword = sourceCode.getFirstToken(node)?.value === keyword;
1938
+ const isSameType = Array.isArray(type) ? type.includes(node.type) : type === node.type;
1939
+ return isSameKeyword && isSameType;
1940
+ }
1941
+ };
1942
+ }
1943
+ function newNodeTypeTester(type) {
1944
+ return {
1945
+ test: (node) => node.type === type
1946
+ };
1947
+ }
1948
+ function isIIFEStatement(node) {
1949
+ if (node.type === "ExpressionStatement") {
1950
+ let expression = skipChainExpression(node.expression);
1951
+ if (expression.type === "UnaryExpression")
1952
+ expression = skipChainExpression(expression.argument);
1953
+ if (expression.type === "CallExpression") {
1954
+ let node = expression.callee;
1955
+ while (node.type === "SequenceExpression") {
1956
+ const lastExpression = node.expressions.at(-1);
1957
+ if (lastExpression === undefined)
1958
+ throw new Error("Padding rule invariant: sequence expression is empty");
1959
+ node = lastExpression;
1960
+ }
1961
+ return isFunction(node);
1962
+ }
1963
+ }
1964
+ return false;
1965
+ }
1966
+ function isCJSRequire(node) {
1967
+ if (node.type === "VariableDeclaration") {
1968
+ const declaration = node.declarations[0];
1969
+ if (declaration?.init) {
1970
+ let call = declaration?.init;
1971
+ while (call.type === "MemberExpression")
1972
+ call = call.object;
1973
+ if (call.type === "CallExpression" && call.callee.type === "Identifier") {
1974
+ return call.callee.name === "require";
1975
+ }
1976
+ }
1977
+ }
1978
+ return false;
1979
+ }
1980
+ function isBlockLikeStatement(node, sourceCode) {
1981
+ if (node.type === "DoWhileStatement" && node.body.type === "BlockStatement") {
1982
+ return true;
1983
+ }
1984
+ if (isIIFEStatement(node))
1985
+ return true;
1986
+ const lastToken = sourceCode.getLastToken(node, isNotSemicolonToken);
1987
+ const belongingNode = lastToken && isClosingBraceToken(lastToken) ? sourceCode.getNodeByRangeIndex(lastToken.range[0]) : null;
1988
+ return !!belongingNode && (belongingNode.type === "BlockStatement" || belongingNode.type === "SwitchStatement");
1989
+ }
1990
+ function isDirective(node, sourceCode) {
1991
+ return isTopLevelExpressionStatement(node) && node.expression.type === "Literal" && typeof node.expression.value === "string" && !isParenthesized(node.expression, sourceCode);
1992
+ }
1993
+ function isDirectivePrologue(node, sourceCode) {
1994
+ if (isDirective(node, sourceCode) && node.parent && "body" in node.parent && Array.isArray(node.parent.body)) {
1995
+ for (const sibling of node.parent.body) {
1996
+ if (sibling === node)
1997
+ break;
1998
+ if (!isDirective(sibling, sourceCode))
1999
+ return false;
2000
+ }
2001
+ return true;
2002
+ }
2003
+ return false;
2004
+ }
2005
+ function isCJSExport(node) {
2006
+ if (node.type === "ExpressionStatement") {
2007
+ const expression = node.expression;
2008
+ if (expression.type === "AssignmentExpression") {
2009
+ let left = expression.left;
2010
+ if (left.type === "MemberExpression") {
2011
+ while (left.object.type === "MemberExpression")
2012
+ left = left.object;
2013
+ return left.object.type === "Identifier" && (left.object.name === "exports" || left.object.name === "module" && left.property.type === "Identifier" && left.property.name === "exports");
2014
+ }
2015
+ }
2016
+ }
2017
+ return false;
2018
+ }
2019
+ function isExpression(node, sourceCode) {
2020
+ return node.type === "ExpressionStatement" && !isDirectivePrologue(node, sourceCode);
2021
+ }
2022
+ function getActualLastToken(node, sourceCode) {
2023
+ const semiToken = sourceCode.getLastToken(node);
2024
+ const prevToken = sourceCode.getTokenBefore(semiToken);
2025
+ const nextToken = sourceCode.getTokenAfter(semiToken);
2026
+ const isSemicolonLessStyle = prevToken && nextToken && prevToken.range[0] >= node.range[0] && isSemicolonToken(semiToken) && !isTokenOnSameLine(prevToken, semiToken) && isTokenOnSameLine(semiToken, nextToken);
2027
+ return isSemicolonLessStyle ? prevToken : semiToken;
2028
+ }
2029
+ function replacerToRemovePaddingLines(_, trailingSpaces, indentSpaces) {
2030
+ return trailingSpaces + indentSpaces;
2031
+ }
2032
+ function getReportLoc(node, sourceCode) {
2033
+ if (isSingleLine(node))
2034
+ return node.loc;
2035
+ const line = node.loc.start.line;
2036
+ const sourceLine = sourceCode.lines[line - 1];
2037
+ if (sourceLine === undefined)
2038
+ throw new Error("Padding rule invariant: statement source line is missing");
2039
+ return {
2040
+ start: node.loc.start,
2041
+ end: {
2042
+ line,
2043
+ column: sourceLine.length
2044
+ }
2045
+ };
2046
+ }
2047
+ function verifyForAny() {}
2048
+ function verifyForNever(context, _, nextNode, paddingLines) {
2049
+ if (paddingLines.length === 0)
2050
+ return;
2051
+ context.report({
2052
+ node: nextNode,
2053
+ messageId: "unexpectedBlankLine",
2054
+ loc: getReportLoc(nextNode, context.sourceCode),
2055
+ fix(fixer) {
2056
+ if (paddingLines.length >= 2)
2057
+ return null;
2058
+ const paddingPair = paddingLines[0];
2059
+ if (paddingPair === undefined)
2060
+ throw new Error("Padding rule invariant: reported padding pair is missing");
2061
+ const [prevToken, nextToken] = paddingPair;
2062
+ const start = prevToken.range[1];
2063
+ const end = nextToken.range[0];
2064
+ const text = context.sourceCode.text.slice(start, end).replace(PADDING_LINE_SEQUENCE, replacerToRemovePaddingLines);
2065
+ return fixer.replaceTextRange([start, end], text);
2066
+ }
2067
+ });
2068
+ }
2069
+ function verifyForAlways(context, prevNode, nextNode, paddingLines) {
2070
+ if (paddingLines.length > 0)
2071
+ return;
2072
+ context.report({
2073
+ node: nextNode,
2074
+ messageId: "expectedBlankLine",
2075
+ loc: getReportLoc(nextNode, context.sourceCode),
2076
+ fix(fixer) {
2077
+ const sourceCode = context.sourceCode;
2078
+ let prevToken = getActualLastToken(prevNode, sourceCode);
2079
+ const nextToken = sourceCode.getFirstTokenBetween(prevToken, nextNode, {
2080
+ includeComments: true,
2081
+ filter(token) {
2082
+ if (isTokenOnSameLine(prevToken, token)) {
2083
+ prevToken = token;
2084
+ return false;
2085
+ }
2086
+ return true;
2087
+ }
2088
+ }) || nextNode;
2089
+ const insertText = isTokenOnSameLine(prevToken, nextToken) ? `
2090
+
2091
+ ` : `
2092
+ `;
2093
+ return fixer.insertTextAfter(prevToken, insertText);
2094
+ }
2095
+ });
2096
+ }
2097
+ var PaddingTypes = {
2098
+ any: { verify: verifyForAny },
2099
+ never: { verify: verifyForNever },
2100
+ always: { verify: verifyForAlways }
2101
+ };
2102
+ var MaybeMultilineStatementType = {
2103
+ "block-like": { test: isBlockLikeStatement },
2104
+ expression: { test: isExpression },
2105
+ return: newKeywordTester("ReturnStatement", "return"),
2106
+ export: newKeywordTester([
2107
+ "ExportAllDeclaration",
2108
+ "ExportDefaultDeclaration",
2109
+ "ExportNamedDeclaration"
2110
+ ], "export"),
2111
+ var: newKeywordTester("VariableDeclaration", "var"),
2112
+ let: newKeywordTester("VariableDeclaration", "let"),
2113
+ const: newKeywordTester("VariableDeclaration", "const"),
2114
+ using: {
2115
+ test: (node) => node.type === "VariableDeclaration" && (node.kind === "using" || node.kind === "await using")
2116
+ },
2117
+ type: newKeywordTester("TSTypeAliasDeclaration", "type")
2118
+ };
2119
+ var StatementTypes = {
2120
+ "*": { test: () => true },
2121
+ exports: { test: isCJSExport },
2122
+ require: { test: isCJSRequire },
2123
+ directive: { test: isDirectivePrologue },
2124
+ iife: { test: isIIFEStatement },
2125
+ block: newNodeTypeTester("BlockStatement"),
2126
+ empty: newNodeTypeTester("EmptyStatement"),
2127
+ function: newNodeTypeTester("FunctionDeclaration"),
2128
+ "ts-method": newNodeTypeTester("TSMethodSignature"),
2129
+ break: newKeywordTester("BreakStatement", "break"),
2130
+ case: newKeywordTester("SwitchCase", "case"),
2131
+ class: newKeywordTester("ClassDeclaration", "class"),
2132
+ continue: newKeywordTester("ContinueStatement", "continue"),
2133
+ debugger: newKeywordTester("DebuggerStatement", "debugger"),
2134
+ default: newKeywordTester(["SwitchCase", "ExportDefaultDeclaration"], "default"),
2135
+ do: newKeywordTester("DoWhileStatement", "do"),
2136
+ for: newKeywordTester([
2137
+ "ForStatement",
2138
+ "ForInStatement",
2139
+ "ForOfStatement"
2140
+ ], "for"),
2141
+ if: newKeywordTester("IfStatement", "if"),
2142
+ import: newKeywordTester("ImportDeclaration", "import"),
2143
+ switch: newKeywordTester("SwitchStatement", "switch"),
2144
+ throw: newKeywordTester("ThrowStatement", "throw"),
2145
+ try: newKeywordTester("TryStatement", "try"),
2146
+ while: newKeywordTester(["WhileStatement", "DoWhileStatement"], "while"),
2147
+ with: newKeywordTester("WithStatement", "with"),
2148
+ "cjs-export": {
2149
+ test: (node, sourceCode) => node.type === "ExpressionStatement" && node.expression.type === "AssignmentExpression" && CJS_EXPORT.test(sourceCode.getText(node.expression.left))
2150
+ },
2151
+ "cjs-import": {
2152
+ test: (node, sourceCode) => node.type === "VariableDeclaration" && node.declarations.length > 0 && node.declarations[0]?.init != null && CJS_IMPORT.test(sourceCode.getText(node.declarations[0].init))
2153
+ },
2154
+ enum: newKeywordTester("TSEnumDeclaration", "enum"),
2155
+ interface: newKeywordTester("TSInterfaceDeclaration", "interface"),
2156
+ "function-overload": newNodeTypeTester("TSDeclareFunction"),
2157
+ ...Object.fromEntries(Object.entries(MaybeMultilineStatementType).flatMap(([key, value]) => [
2158
+ [key, value],
2159
+ [
2160
+ `singleline-${key}`,
2161
+ {
2162
+ ...value,
2163
+ test: (node, sourceCode) => value.test(node, sourceCode) && isSingleLine(node)
2164
+ }
2165
+ ],
2166
+ [
2167
+ `multiline-${key}`,
2168
+ {
2169
+ ...value,
2170
+ test: (node, sourceCode) => value.test(node, sourceCode) && !isSingleLine(node)
2171
+ }
2172
+ ]
2173
+ ]))
2174
+ };
2175
+ function createPaddingLineRule(options) {
2176
+ return {
2177
+ meta: {
2178
+ type: "layout",
2179
+ docs: {
2180
+ description: "Require or disallow padding lines between statements"
2181
+ },
2182
+ fixable: "whitespace",
2183
+ hasSuggestions: false,
2184
+ schema: {
2185
+ $defs: {
2186
+ paddingType: {
2187
+ type: "string",
2188
+ enum: Object.keys(PaddingTypes)
2189
+ },
2190
+ statementType: {
2191
+ type: "string",
2192
+ enum: Object.keys(StatementTypes)
2193
+ },
2194
+ selectorOption: {
2195
+ type: "object",
2196
+ properties: {
2197
+ selector: {
2198
+ type: "string"
2199
+ },
2200
+ lineMode: {
2201
+ type: "string",
2202
+ enum: ["any", "singleline", "multiline"]
2203
+ }
2204
+ },
2205
+ required: ["selector"],
2206
+ additionalProperties: false
2207
+ },
2208
+ statementMatcher: {
2209
+ anyOf: [
2210
+ { $ref: "#/$defs/statementType" },
2211
+ { $ref: "#/$defs/selectorOption" }
2212
+ ]
2213
+ },
2214
+ statementOption: {
2215
+ anyOf: [
2216
+ { $ref: "#/$defs/statementMatcher" },
2217
+ {
2218
+ type: "array",
2219
+ items: { $ref: "#/$defs/statementMatcher" },
2220
+ minItems: 1,
2221
+ uniqueItems: true,
2222
+ additionalItems: false
2223
+ }
2224
+ ]
2225
+ }
2226
+ },
2227
+ type: "array",
2228
+ additionalItems: false,
2229
+ items: {
2230
+ type: "object",
2231
+ properties: {
2232
+ blankLine: { $ref: "#/$defs/paddingType" },
2233
+ prev: { $ref: "#/$defs/statementOption" },
2234
+ next: { $ref: "#/$defs/statementOption" }
2235
+ },
2236
+ additionalProperties: false,
2237
+ required: ["blankLine", "prev", "next"]
2238
+ }
2239
+ },
2240
+ messages: {
2241
+ unexpectedBlankLine: "Unexpected blank line before this statement.",
2242
+ expectedBlankLine: "Expected blank line before this statement."
2243
+ }
2244
+ },
2245
+ create(context) {
2246
+ const sourceCode = context.sourceCode;
2247
+ const selectorMatchedNodes = new Map;
2248
+ const pendingPairs = [];
2249
+ function collectSelectorOption(option) {
2250
+ if (Array.isArray(option)) {
2251
+ for (const item of option)
2252
+ collectSelectorOption(item);
2253
+ return;
2254
+ }
2255
+ if (!isSelectorOption(option))
2256
+ return;
2257
+ selectorMatchedNodes.set(option.selector, new Set);
2258
+ }
2259
+ for (const configure of options) {
2260
+ collectSelectorOption(configure.prev);
2261
+ collectSelectorOption(configure.next);
2262
+ }
2263
+ let scopeInfo = null;
2264
+ function enterScope() {
2265
+ scopeInfo = {
2266
+ upper: scopeInfo,
2267
+ prevNode: null
2268
+ };
2269
+ }
2270
+ function exitScope() {
2271
+ if (scopeInfo)
2272
+ scopeInfo = scopeInfo.upper;
2273
+ }
2274
+ function match(node, type) {
2275
+ let innerStatementNode = node;
2276
+ while (innerStatementNode.type === "LabeledStatement")
2277
+ innerStatementNode = innerStatementNode.body;
2278
+ if (Array.isArray(type))
2279
+ return type.some(match.bind(null, innerStatementNode));
2280
+ if (isSelectorOption(type)) {
2281
+ const matchedNodes = selectorMatchedNodes.get(type.selector);
2282
+ if (!matchedNodes?.has(innerStatementNode))
2283
+ return false;
2284
+ const lineMode = type.lineMode;
2285
+ if (lineMode === "singleline")
2286
+ return isSingleLine(innerStatementNode);
2287
+ else if (lineMode === "multiline")
2288
+ return !isSingleLine(innerStatementNode);
2289
+ return true;
2290
+ } else {
2291
+ const statementType = StatementTypes[type];
2292
+ if (statementType === undefined)
2293
+ throw new Error(`Padding rule invariant: unsupported statement type ${type}`);
2294
+ return statementType.test(innerStatementNode, sourceCode);
2295
+ }
2296
+ }
2297
+ function getPaddingType(prevNode, nextNode) {
2298
+ for (let i = options.length - 1;i >= 0; --i) {
2299
+ const configure = options[i];
2300
+ if (configure === undefined)
2301
+ throw new Error("Padding rule invariant: configuration entry is missing");
2302
+ if (match(prevNode, configure.prev) && match(nextNode, configure.next)) {
2303
+ return PaddingTypes[configure.blankLine];
2304
+ }
2305
+ }
2306
+ return PaddingTypes.any;
2307
+ }
2308
+ function getPaddingLineSequences(prevNode, nextNode) {
2309
+ const pairs = [];
2310
+ let prevToken = getActualLastToken(prevNode, sourceCode);
2311
+ if (nextNode.loc.start.line - prevToken.loc.end.line >= 2) {
2312
+ do {
2313
+ const token = sourceCode.getTokenAfter(prevToken, {
2314
+ includeComments: true
2315
+ });
2316
+ if (token.loc.start.line - prevToken.loc.end.line >= 2)
2317
+ pairs.push([prevToken, token]);
2318
+ prevToken = token;
2319
+ } while (prevToken.range[0] < nextNode.range[0]);
2320
+ }
2321
+ return pairs;
2322
+ }
2323
+ function verify(node) {
2324
+ if (!node.parent || ![
2325
+ "BlockStatement",
2326
+ "Program",
2327
+ "StaticBlock",
2328
+ "SwitchCase",
2329
+ "SwitchStatement",
2330
+ "TSInterfaceBody",
2331
+ "TSModuleBlock",
2332
+ "TSTypeLiteral"
2333
+ ].includes(node.parent.type)) {
2334
+ return;
2335
+ }
2336
+ const prevNode = scopeInfo.prevNode;
2337
+ if (prevNode)
2338
+ pendingPairs.push({ prevNode, nextNode: node });
2339
+ scopeInfo.prevNode = node;
2340
+ }
2341
+ function verifyPendingPairs() {
2342
+ for (const { prevNode, nextNode } of pendingPairs) {
2343
+ const type = getPaddingType(prevNode, nextNode);
2344
+ const paddingLines = getPaddingLineSequences(prevNode, nextNode);
2345
+ type.verify(context, prevNode, nextNode, paddingLines);
2346
+ }
2347
+ }
2348
+ function verifyThenEnterScope(node) {
2349
+ verify(node);
2350
+ enterScope();
2351
+ }
2352
+ const selectorMatchListeners = Object.fromEntries(Array.from(selectorMatchedNodes.keys(), (selector) => [
2353
+ selector,
2354
+ (node) => {
2355
+ selectorMatchedNodes.get(selector)?.add(node);
2356
+ }
2357
+ ]));
2358
+ return {
2359
+ Program: enterScope,
2360
+ "Program:exit": () => {
2361
+ verifyPendingPairs();
2362
+ exitScope();
2363
+ },
2364
+ BlockStatement: enterScope,
2365
+ "BlockStatement:exit": exitScope,
2366
+ SwitchStatement: enterScope,
2367
+ "SwitchStatement:exit": exitScope,
2368
+ SwitchCase: verifyThenEnterScope,
2369
+ "SwitchCase:exit": exitScope,
2370
+ StaticBlock: enterScope,
2371
+ "StaticBlock:exit": exitScope,
2372
+ TSInterfaceBody: enterScope,
2373
+ "TSInterfaceBody:exit": exitScope,
2374
+ TSModuleBlock: enterScope,
2375
+ "TSModuleBlock:exit": exitScope,
2376
+ TSTypeLiteral: enterScope,
2377
+ "TSTypeLiteral:exit": exitScope,
2378
+ TSDeclareFunction: verifyThenEnterScope,
2379
+ "TSDeclareFunction:exit": exitScope,
2380
+ TSMethodSignature: verifyThenEnterScope,
2381
+ "TSMethodSignature:exit": exitScope,
2382
+ ":statement": verify,
2383
+ ...selectorMatchListeners
2384
+ };
2385
+ }
2386
+ };
2387
+ }
2388
+
2389
+ // vendor/anti-slop/src/rules/require-readable-spacing.ts
2390
+ var paddingRule = createPaddingLineRule([
2391
+ { blankLine: "always", prev: "import", next: "*" },
2392
+ { blankLine: "always", prev: "*", next: { selector: "Program > :not(ImportDeclaration)" } },
2393
+ { blankLine: "always", prev: { selector: "Program > :not(ImportDeclaration)" }, next: "*" },
2394
+ { blankLine: "always", prev: "*", next: ["function", "class", "interface", "type"] },
2395
+ { blankLine: "always", prev: ["function", "class", "interface", "type"], next: "*" },
2396
+ {
2397
+ blankLine: "always",
2398
+ prev: "*",
2399
+ next: ["multiline-const", "multiline-let", "multiline-var", "multiline-using"]
2400
+ },
2401
+ {
2402
+ blankLine: "always",
2403
+ prev: ["multiline-const", "multiline-let", "multiline-var", "multiline-using"],
2404
+ next: "*"
2405
+ },
2406
+ { blankLine: "always", prev: "*", next: ["return", "if", "switch", "try", "for", "while", "do"] },
2407
+ { blankLine: "always", prev: "block-like", next: "*" },
2408
+ { blankLine: "any", prev: "import", next: "import" },
2409
+ {
2410
+ blankLine: "any",
2411
+ prev: {
2412
+ selector: ':matches(TSDeclareFunction, ExportNamedDeclaration[declaration.type="TSDeclareFunction"])'
2413
+ },
2414
+ next: {
2415
+ selector: ':matches(TSDeclareFunction, FunctionDeclaration, ExportNamedDeclaration[declaration.type="TSDeclareFunction"], ExportNamedDeclaration[declaration.type="FunctionDeclaration"])'
2416
+ }
2417
+ }
2418
+ ]);
2419
+ var requireReadableSpacingRule = {
2420
+ ...paddingRule,
2421
+ meta: {
2422
+ ...paddingRule.meta,
2423
+ docs: {
2424
+ description: "Require readable spacing between declarations and logical statement groups."
2425
+ },
2426
+ schema: []
2427
+ }
2428
+ };
2429
+
1723
2430
  // vendor/anti-slop/src/rules/require-safety-comment-for-type-assertion.ts
1724
- import { defineRule as defineRule15 } from "@oxlint/plugins";
2431
+ import { defineRule as defineRule17 } from "@oxlint/plugins";
1725
2432
  var DEFAULT_SAFETY_MARKERS = ["SAFETY"];
1726
2433
  var commentOwnerKinds = new Set([
1727
2434
  "ExpressionStatement",
@@ -1764,7 +2471,7 @@ function hasSafetyComment(sourceCode, node, pattern) {
1764
2471
  current = current.parent;
1765
2472
  }
1766
2473
  }
1767
- var requireSafetyCommentForTypeAssertionRule = defineRule15({
2474
+ var requireSafetyCommentForTypeAssertionRule = defineRule17({
1768
2475
  meta: {
1769
2476
  type: "problem",
1770
2477
  docs: {
@@ -1817,6 +2524,8 @@ var requireSafetyCommentForTypeAssertionRule = defineRule15({
1817
2524
  var antiSlopPlugin = eslintCompatPlugin({
1818
2525
  meta: { name: "anti-slop" },
1819
2526
  rules: {
2527
+ "no-array-filter-map": noArrayFilterMapRule,
2528
+ "no-reduce-accumulator-copy": noReduceAccumulatorCopyRule,
1820
2529
  "no-chained-type-assertions": noChainedTypeAssertionsRule,
1821
2530
  "no-conditional-empty-object-spread": noConditionalEmptyObjectSpreadRule,
1822
2531
  "no-known-value-widening": noKnownValueWideningRule,
@@ -1831,6 +2540,7 @@ var antiSlopPlugin = eslintCompatPlugin({
1831
2540
  "no-unknown-returns": noUnknownReturnsRule,
1832
2541
  "no-unknown-type-aliases": noUnknownTypeAliasesRule,
1833
2542
  "no-widen-then-assert": noWidenThenAssertRule,
2543
+ "require-readable-spacing": requireReadableSpacingRule,
1834
2544
  "require-safety-comment-for-type-assertion": requireSafetyCommentForTypeAssertionRule
1835
2545
  }
1836
2546
  });
@@ -1839,7 +2549,7 @@ var src_default = antiSlopPlugin;
1839
2549
  import { eslintCompatPlugin as eslintCompatPlugin2 } from "@oxlint/plugins";
1840
2550
 
1841
2551
  // src/generic/rules/prefer-event-parameter-type.ts
1842
- import { defineRule as defineRule16 } from "@oxlint/plugins";
2552
+ import { defineRule as defineRule18 } from "@oxlint/plugins";
1843
2553
  function nearestEnclosingFunction(node) {
1844
2554
  let current = node.parent;
1845
2555
  while (current) {
@@ -1866,7 +2576,7 @@ function assertedEventParameter(node) {
1866
2576
  property
1867
2577
  };
1868
2578
  }
1869
- var preferEventParameterTypeRule = defineRule16({
2579
+ var preferEventParameterTypeRule = defineRule18({
1870
2580
  meta: {
1871
2581
  type: "suggestion",
1872
2582
  docs: {
@@ -1903,11 +2613,6 @@ var timmoPlugin = eslintCompatPlugin2({
1903
2613
  });
1904
2614
  var generic_default = timmoPlugin;
1905
2615
 
1906
- // node_modules/oxlint/dist/index.js
1907
- function defineConfig(config) {
1908
- return config;
1909
- }
1910
-
1911
2616
  // src/configs/enable-plugin-rules.ts
1912
2617
  function enablePluginRules(namespace, plugin) {
1913
2618
  return Object.fromEntries(Object.keys(plugin.rules).sort().map((rule) => [`${namespace}/${rule}`, "error"]));
@@ -1933,8 +2638,8 @@ var recommended_default = recommended;
1933
2638
  import { eslintCompatPlugin as eslintCompatPlugin3 } from "@oxlint/plugins";
1934
2639
 
1935
2640
  // src/effect/rules/no-try-catch-in-effect-generators.ts
1936
- import { defineRule as defineRule17 } from "@oxlint/plugins";
1937
- function resolveVariable4(sourceCode, identifier) {
2641
+ import { defineRule as defineRule19 } from "@oxlint/plugins";
2642
+ function resolveVariable2(sourceCode, identifier) {
1938
2643
  let scope = sourceCode.getScope(identifier);
1939
2644
  while (scope) {
1940
2645
  const variable = scope.set.get(identifier.name);
@@ -1960,7 +2665,7 @@ function staticMemberName(node) {
1960
2665
  return node.property.type === "Identifier" ? node.property.name : null;
1961
2666
  }
1962
2667
  function isEffectImport(sourceCode, identifier, namespace) {
1963
- const variable = resolveVariable4(sourceCode, identifier);
2668
+ const variable = resolveVariable2(sourceCode, identifier);
1964
2669
  return variable?.defs.some((definition) => {
1965
2670
  if (definition.type !== "ImportBinding" || definition.parent?.type !== "ImportDeclaration" || definition.parent.source.value !== "effect") {
1966
2671
  return false;
@@ -1999,7 +2704,7 @@ function isRecognisedEffectGenerator(sourceCode, owner) {
1999
2704
  const factoryCall = parent.callee;
2000
2705
  return factoryCall.type === "CallExpression" && isEffectMethod(sourceCode, factoryCall.callee, "fn");
2001
2706
  }
2002
- var noTryCatchInEffectGeneratorsRule = defineRule17({
2707
+ var noTryCatchInEffectGeneratorsRule = defineRule19({
2003
2708
  meta: {
2004
2709
  type: "problem",
2005
2710
  docs: {
@@ -2036,8 +2741,149 @@ var effect_default = timmoEffectPlugin;
2036
2741
  // vendor/anti-slop/src/effect/index.ts
2037
2742
  import { eslintCompatPlugin as eslintCompatPlugin4 } from "@oxlint/plugins";
2038
2743
 
2744
+ // vendor/anti-slop/src/effect/rules/no-manual-effect-error-tag.ts
2745
+ import { defineRule as defineRule20 } from "@oxlint/plugins";
2746
+
2747
+ // vendor/anti-slop/src/effect/shared/tagged-values.ts
2748
+ var equalityOperators = new Set(["==", "===", "!=", "!=="]);
2749
+ var broadEffectCatchMethods = new Set(["catch", "catchAll", "catchIf"]);
2750
+ var isStringLiteral = (node) => node?.type === "Literal" && typeof node.value === "string";
2751
+ var isTagMember = (node) => node?.type === "MemberExpression" && (!node.computed && node.property.type === "Identifier" && node.property.name === "_tag" || node.computed && isStringLiteral(node.property) && node.property.value === "_tag");
2752
+ var tagMemberFromComparison = (node) => {
2753
+ if (!equalityOperators.has(node.operator))
2754
+ return;
2755
+ if (isTagMember(node.left) && isStringLiteral(node.right))
2756
+ return node.left;
2757
+ if (isTagMember(node.right) && isStringLiteral(node.left))
2758
+ return node.right;
2759
+ return;
2760
+ };
2761
+ var isBroadEffectCatchCall = (node) => node?.type === "CallExpression" && node.callee.type === "MemberExpression" && node.callee.object.type === "Identifier" && node.callee.object.name === "Effect" && !node.callee.computed && node.callee.property.type === "Identifier" && broadEffectCatchMethods.has(node.callee.property.name);
2762
+ var isInsideBroadEffectHandler = (node) => {
2763
+ let current = node.parent;
2764
+ while (current !== null && current !== undefined) {
2765
+ if (current.type === "ArrowFunctionExpression" || current.type === "FunctionExpression") {
2766
+ return isBroadEffectCatchCall(current.parent) && current.parent.arguments.includes(current);
2767
+ }
2768
+ current = current.parent;
2769
+ }
2770
+ return false;
2771
+ };
2772
+ var isReasonTagMember = (node) => node.object.type === "MemberExpression" && (!node.object.computed && node.object.property.type === "Identifier" && node.object.property.name === "reason" || node.object.computed && isStringLiteral(node.object.property) && node.object.property.value === "reason");
2773
+ var propertyName = (property) => {
2774
+ if (!property.computed && property.key.type === "Identifier") {
2775
+ return property.key.name;
2776
+ }
2777
+ if (property.key.type === "Literal" && typeof property.key.value === "string") {
2778
+ return property.key.value;
2779
+ }
2780
+ return;
2781
+ };
2782
+ var isMatchPatternObject = (node) => {
2783
+ const call = node.parent;
2784
+ if (call?.type !== "CallExpression" || !call.arguments.includes(node)) {
2785
+ return false;
2786
+ }
2787
+ const callee = call.callee;
2788
+ return callee.type === "MemberExpression" && callee.object.type === "Identifier" && callee.object.name === "Match" && !callee.computed && callee.property.type === "Identifier" && (callee.property.name === "when" || callee.property.name === "not");
2789
+ };
2790
+
2791
+ // vendor/anti-slop/src/effect/rules/no-manual-effect-error-tag.ts
2792
+ var noManualEffectErrorTagRule = defineRule20({
2793
+ meta: {
2794
+ type: "problem",
2795
+ docs: {
2796
+ description: "Use Effect tagged error handlers instead of manually branching on `_tag` in a catch handler."
2797
+ },
2798
+ messages: {
2799
+ tag: "Use Effect.catchTag or Effect.catchTags instead of manually discriminating a tagged error in a broad Effect catch handler.",
2800
+ reason: "Use Effect.catchReason or Effect.catchReasons instead of manually discriminating a tagged `reason` in a broad Effect catch handler."
2801
+ }
2802
+ },
2803
+ createOnce(context) {
2804
+ return {
2805
+ BinaryExpression(node) {
2806
+ const tagMember = tagMemberFromComparison(node);
2807
+ if (tagMember === undefined || !isInsideBroadEffectHandler(node)) {
2808
+ return;
2809
+ }
2810
+ context.report({
2811
+ node,
2812
+ messageId: isReasonTagMember(tagMember) ? "reason" : "tag"
2813
+ });
2814
+ },
2815
+ SwitchStatement(node) {
2816
+ if (!isTagMember(node.discriminant) || !isInsideBroadEffectHandler(node)) {
2817
+ return;
2818
+ }
2819
+ context.report({
2820
+ node,
2821
+ messageId: isReasonTagMember(node.discriminant) ? "reason" : "tag"
2822
+ });
2823
+ }
2824
+ };
2825
+ }
2826
+ });
2827
+
2828
+ // vendor/anti-slop/src/effect/rules/no-manual-tag-comparison.ts
2829
+ import { defineRule as defineRule21 } from "@oxlint/plugins";
2830
+ var noManualTagComparisonRule = defineRule21({
2831
+ meta: {
2832
+ type: "problem",
2833
+ docs: {
2834
+ description: "Use Effect Match or Predicate helpers instead of manually branching on `_tag`."
2835
+ },
2836
+ messages: {
2837
+ manualComparison: "Use Match.tag/Match.tags for tagged-value branching, or Predicate.isTagged for a simple reusable predicate.",
2838
+ manualSwitch: "Use Match.value(value).pipe(Match.tag/Match.tags/Match.tagsExhaustive) or the tagged enum `$match` helper instead of switching on `_tag`."
2839
+ }
2840
+ },
2841
+ createOnce(context) {
2842
+ return {
2843
+ BinaryExpression(node) {
2844
+ if (tagMemberFromComparison(node) === undefined || isInsideBroadEffectHandler(node)) {
2845
+ return;
2846
+ }
2847
+ context.report({ node, messageId: "manualComparison" });
2848
+ },
2849
+ SwitchStatement(node) {
2850
+ if (!isTagMember(node.discriminant) || isInsideBroadEffectHandler(node)) {
2851
+ return;
2852
+ }
2853
+ context.report({ node, messageId: "manualSwitch" });
2854
+ }
2855
+ };
2856
+ }
2857
+ });
2858
+
2859
+ // vendor/anti-slop/src/effect/rules/no-manual-tagged-construction.ts
2860
+ import { defineRule as defineRule22 } from "@oxlint/plugins";
2861
+ var noManualTaggedConstructionRule = defineRule22({
2862
+ meta: {
2863
+ type: "problem",
2864
+ docs: {
2865
+ description: "Construct tagged values with their existing Effect constructor instead of writing `_tag` manually."
2866
+ },
2867
+ messages: {
2868
+ manualConstruction: "Use the existing Schema tagged `.make`, tagged class/error constructor, or Data.taggedEnum variant constructor instead of writing a literal `_tag` object."
2869
+ }
2870
+ },
2871
+ createOnce(context) {
2872
+ return {
2873
+ ObjectExpression(node) {
2874
+ if (isMatchPatternObject(node))
2875
+ return;
2876
+ const tag = node.properties.find((property) => property.type === "Property" && propertyName(property) === "_tag" && isStringLiteral(property.value));
2877
+ if (tag !== undefined) {
2878
+ context.report({ node: tag, messageId: "manualConstruction" });
2879
+ }
2880
+ }
2881
+ };
2882
+ }
2883
+ });
2884
+
2039
2885
  // vendor/anti-slop/src/effect/rules/no-service-constructor-imports.ts
2040
- import { defineRule as defineRule18 } from "@oxlint/plugins";
2886
+ import { defineRule as defineRule23 } from "@oxlint/plugins";
2041
2887
  var SERVICE_CONSTRUCTOR_NAME = /^make[A-Z]/u;
2042
2888
  var TEST_FILE = /\.(?:test|spec)\.[cm]?[jt]sx?$/u;
2043
2889
  function isProjectLocalImport(source) {
@@ -2048,7 +2894,7 @@ function getImportedName(specifier) {
2048
2894
  return specifier.imported.name;
2049
2895
  return specifier.imported.value;
2050
2896
  }
2051
- var noServiceConstructorImportsRule = defineRule18({
2897
+ var noServiceConstructorImportsRule = defineRule23({
2052
2898
  meta: {
2053
2899
  type: "problem",
2054
2900
  docs: {
@@ -2067,13 +2913,13 @@ var noServiceConstructorImportsRule = defineRule18({
2067
2913
  for (const specifier of node.specifiers) {
2068
2914
  if (specifier.type !== "ImportSpecifier")
2069
2915
  continue;
2070
- const importedName2 = getImportedName(specifier);
2071
- if (!SERVICE_CONSTRUCTOR_NAME.test(importedName2))
2916
+ const importedName = getImportedName(specifier);
2917
+ if (!SERVICE_CONSTRUCTOR_NAME.test(importedName))
2072
2918
  continue;
2073
2919
  context.report({
2074
2920
  node: specifier,
2075
2921
  messageId: "serviceConstructorImport",
2076
- data: { name: importedName2 }
2922
+ data: { name: importedName }
2077
2923
  });
2078
2924
  }
2079
2925
  }
@@ -2081,11 +2927,63 @@ var noServiceConstructorImportsRule = defineRule18({
2081
2927
  }
2082
2928
  });
2083
2929
 
2930
+ // vendor/anti-slop/src/effect/rules/prefer-effect-match.ts
2931
+ import { defineRule as defineRule24 } from "@oxlint/plugins";
2932
+ var equalityOperators2 = new Set(["==", "===", "!=", "!=="]);
2933
+ var preferEffectMatchRule = defineRule24({
2934
+ meta: {
2935
+ type: "problem",
2936
+ docs: {
2937
+ description: "Use Match from Effect for chained literal ternaries over the same value."
2938
+ },
2939
+ messages: {
2940
+ preferMatch: "Use Match from Effect instead of a chained literal ternary."
2941
+ }
2942
+ },
2943
+ createOnce(context) {
2944
+ const isLiteral = (node) => node.type === "Literal" || node.type === "TemplateLiteral" && node.expressions.length === 0;
2945
+ const comparedValue = (node) => {
2946
+ if (node.type !== "BinaryExpression" || !equalityOperators2.has(node.operator)) {
2947
+ return;
2948
+ }
2949
+ if (isLiteral(node.left))
2950
+ return context.sourceCode.getText(node.right);
2951
+ if (isLiteral(node.right))
2952
+ return context.sourceCode.getText(node.left);
2953
+ return;
2954
+ };
2955
+ return {
2956
+ ConditionalExpression(node) {
2957
+ if (node.parent?.type === "ConditionalExpression")
2958
+ return;
2959
+ const value = comparedValue(node.test);
2960
+ if (value === undefined)
2961
+ return;
2962
+ let alternate = node.alternate;
2963
+ let literalChecks = 1;
2964
+ while (alternate.type === "ConditionalExpression") {
2965
+ if (comparedValue(alternate.test) !== value)
2966
+ return;
2967
+ literalChecks += 1;
2968
+ alternate = alternate.alternate;
2969
+ }
2970
+ if (literalChecks > 1) {
2971
+ context.report({ node, messageId: "preferMatch" });
2972
+ }
2973
+ }
2974
+ };
2975
+ }
2976
+ });
2977
+
2084
2978
  // vendor/anti-slop/src/effect/index.ts
2085
2979
  var antiSlopEffectPlugin = eslintCompatPlugin4({
2086
2980
  meta: { name: "anti-slop-effect" },
2087
2981
  rules: {
2088
- "no-service-constructor-imports": noServiceConstructorImportsRule
2982
+ "no-manual-effect-error-tag": noManualEffectErrorTagRule,
2983
+ "no-manual-tag-comparison": noManualTagComparisonRule,
2984
+ "no-manual-tagged-construction": noManualTaggedConstructionRule,
2985
+ "no-service-constructor-imports": noServiceConstructorImportsRule,
2986
+ "prefer-effect-match": preferEffectMatchRule
2089
2987
  }
2090
2988
  });
2091
2989
  var effect_default2 = antiSlopEffectPlugin;
@@ -2106,9 +3004,6 @@ var recommendedEffect = defineConfig({
2106
3004
  });
2107
3005
  var recommended_effect_default = recommendedEffect;
2108
3006
 
2109
- // src/cli.ts
2110
- import { resolve as resolve2 } from "node:path";
2111
-
2112
3007
  // src/install/copy.ts
2113
3008
  import { cp, mkdir, readdir, rm } from "node:fs/promises";
2114
3009
  import { dirname, join, relative, resolve, sep } from "node:path";