@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.
- package/README.md +2 -1
- package/THIRD_PARTY_NOTICES.md +9 -0
- package/dist/cli.js +978 -83
- package/dist/configs/recommended-effect.js +1207 -312
- package/dist/configs/recommended.js +772 -70
- package/dist/upstream/anti-slop.js +765 -63
- package/dist/upstream/effect.js +196 -3
- package/package.json +5 -5
- package/vendor/anti-slop/src/effect/index.ts +8 -0
- package/vendor/anti-slop/src/effect/rules/no-manual-effect-error-tag.ts +52 -0
- package/vendor/anti-slop/src/effect/rules/no-manual-tag-comparison.ts +45 -0
- package/vendor/anti-slop/src/effect/rules/no-manual-tagged-construction.ts +37 -0
- package/vendor/anti-slop/src/effect/rules/prefer-effect-match.ts +54 -0
- package/vendor/anti-slop/src/effect/shared/tagged-values.ts +97 -0
- package/vendor/anti-slop/src/index.ts +6 -0
- package/vendor/anti-slop/src/rules/no-array-filter-map.ts +28 -0
- package/vendor/anti-slop/src/rules/no-known-value-widening.ts +2 -14
- package/vendor/anti-slop/src/rules/no-module-mocking.ts +3 -14
- package/vendor/anti-slop/src/rules/no-reduce-accumulator-copy.ts +109 -0
- package/vendor/anti-slop/src/rules/require-readable-spacing.ts +47 -0
- package/vendor/anti-slop/src/shared/array-method.ts +94 -0
- package/vendor/anti-slop/src/shared/reflect-method.ts +2 -13
- package/vendor/anti-slop/src/shared/scope.ts +15 -0
- package/vendor/anti-slop/src/vendor/eslint-stylistic/LICENSE +22 -0
- package/vendor/anti-slop/src/vendor/eslint-stylistic/UPSTREAM.md +28 -0
- package/vendor/anti-slop/src/vendor/eslint-stylistic/padding-line-ast.ts +51 -0
- package/vendor/anti-slop/src/vendor/eslint-stylistic/padding-line-between-statements.ts +906 -0
- package/vendor/anti-slop/src/vendor/eslint-stylistic/padding-line-options.d.ts +87 -0
|
@@ -1,8 +1,203 @@
|
|
|
1
1
|
// vendor/anti-slop/src/index.ts
|
|
2
2
|
import { eslintCompatPlugin } from "@oxlint/plugins";
|
|
3
3
|
|
|
4
|
-
// vendor/anti-slop/src/rules/no-
|
|
4
|
+
// vendor/anti-slop/src/rules/no-array-filter-map.ts
|
|
5
5
|
import { defineRule } from "@oxlint/plugins";
|
|
6
|
+
|
|
7
|
+
// vendor/anti-slop/src/shared/array-method.ts
|
|
8
|
+
function unwrapArrayExpression(node) {
|
|
9
|
+
while (node.type === "ParenthesizedExpression" || node.type === "ChainExpression" || node.type === "TSAsExpression" || node.type === "TSTypeAssertion" || node.type === "TSNonNullExpression" || node.type === "TSSatisfiesExpression") {
|
|
10
|
+
node = node.expression;
|
|
11
|
+
}
|
|
12
|
+
return node;
|
|
13
|
+
}
|
|
14
|
+
function resolveArrayBinding(sourceCode, node) {
|
|
15
|
+
node = unwrapArrayExpression(node);
|
|
16
|
+
if (node.type !== "Identifier")
|
|
17
|
+
return null;
|
|
18
|
+
let scope = sourceCode.getScope(node);
|
|
19
|
+
while (scope !== null) {
|
|
20
|
+
const variable = scope.set.get(node.name);
|
|
21
|
+
if (variable !== undefined)
|
|
22
|
+
return variable;
|
|
23
|
+
scope = scope.upper;
|
|
24
|
+
}
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
function arrayMethodTarget(node) {
|
|
28
|
+
node = unwrapArrayExpression(node);
|
|
29
|
+
if (node.type !== "MemberExpression")
|
|
30
|
+
return null;
|
|
31
|
+
const property = node.property;
|
|
32
|
+
if (!node.computed && property.type === "Identifier") {
|
|
33
|
+
return { name: property.name, object: node.object };
|
|
34
|
+
}
|
|
35
|
+
if (node.computed && property.type === "Literal" && typeof property.value === "string") {
|
|
36
|
+
return { name: property.value, object: node.object };
|
|
37
|
+
}
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
function isArrayAnnotation(type) {
|
|
41
|
+
if (type.type === "TSArrayType" || type.type === "TSTupleType")
|
|
42
|
+
return true;
|
|
43
|
+
if (type.type === "TSParenthesizedType")
|
|
44
|
+
return isArrayAnnotation(type.typeAnnotation);
|
|
45
|
+
if (type.type === "TSTypeOperator" && type.operator === "readonly") {
|
|
46
|
+
return isArrayAnnotation(type.typeAnnotation);
|
|
47
|
+
}
|
|
48
|
+
return type.type === "TSTypeReference" && type.typeName.type === "Identifier" && (type.typeName.name === "Array" || type.typeName.name === "ReadonlyArray");
|
|
49
|
+
}
|
|
50
|
+
function isKnownArrayExpression(sourceCode, node, visited = new Set) {
|
|
51
|
+
node = unwrapArrayExpression(node);
|
|
52
|
+
if (node.type === "ArrayExpression")
|
|
53
|
+
return true;
|
|
54
|
+
if (node.type === "CallExpression") {
|
|
55
|
+
const method = arrayMethodTarget(node.callee);
|
|
56
|
+
return method !== null && ["map", "filter", "flatMap", "slice", "concat", "toSorted", "toReversed", "toSpliced"].includes(method.name) && isKnownArrayExpression(sourceCode, method.object, visited);
|
|
57
|
+
}
|
|
58
|
+
if (node.type !== "Identifier")
|
|
59
|
+
return false;
|
|
60
|
+
const variable = resolveArrayBinding(sourceCode, node);
|
|
61
|
+
if (variable === null || visited.has(variable))
|
|
62
|
+
return false;
|
|
63
|
+
visited.add(variable);
|
|
64
|
+
if (variable.references.some((reference) => reference.isWrite() && !reference.init))
|
|
65
|
+
return false;
|
|
66
|
+
for (const identifier of variable.identifiers) {
|
|
67
|
+
const annotation = identifier.typeAnnotation?.typeAnnotation;
|
|
68
|
+
if (annotation !== undefined)
|
|
69
|
+
return isArrayAnnotation(annotation);
|
|
70
|
+
}
|
|
71
|
+
for (const definition of variable.defs) {
|
|
72
|
+
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") {
|
|
73
|
+
return isKnownArrayExpression(sourceCode, definition.node.init, visited);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// vendor/anti-slop/src/rules/no-array-filter-map.ts
|
|
80
|
+
var noArrayFilterMapRule = defineRule({
|
|
81
|
+
meta: {
|
|
82
|
+
type: "suggestion",
|
|
83
|
+
docs: { description: "Disallow adjacent array filter/map passes in favor of lazy iterator helpers or a single transformation." },
|
|
84
|
+
messages: {
|
|
85
|
+
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."
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
createOnce(context) {
|
|
89
|
+
return {
|
|
90
|
+
CallExpression(node) {
|
|
91
|
+
const outer = arrayMethodTarget(node.callee);
|
|
92
|
+
if (outer === null || outer.name !== "map" && outer.name !== "filter")
|
|
93
|
+
return;
|
|
94
|
+
const innerCall = unwrapArrayExpression(outer.object);
|
|
95
|
+
if (innerCall.type !== "CallExpression")
|
|
96
|
+
return;
|
|
97
|
+
const inner = arrayMethodTarget(innerCall.callee);
|
|
98
|
+
if (inner === null || inner.name !== (outer.name === "map" ? "filter" : "map"))
|
|
99
|
+
return;
|
|
100
|
+
if (!isKnownArrayExpression(context.sourceCode, inner.object))
|
|
101
|
+
return;
|
|
102
|
+
context.report({ node, messageId: "arrayFilterMap", data: { first: inner.name, second: outer.name } });
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// vendor/anti-slop/src/rules/no-reduce-accumulator-copy.ts
|
|
109
|
+
import { defineRule as defineRule2 } from "@oxlint/plugins";
|
|
110
|
+
function enclosingReducer(node) {
|
|
111
|
+
let parent = node.parent;
|
|
112
|
+
while (parent !== null) {
|
|
113
|
+
if (parent.type === "FunctionDeclaration")
|
|
114
|
+
return null;
|
|
115
|
+
if (parent.type === "ArrowFunctionExpression" || parent.type === "FunctionExpression") {
|
|
116
|
+
const callback = parent;
|
|
117
|
+
let owner = callback.parent;
|
|
118
|
+
while (owner !== null && unwrapArrayExpression(owner) === callback)
|
|
119
|
+
owner = owner.parent;
|
|
120
|
+
if (owner?.type !== "CallExpression")
|
|
121
|
+
return null;
|
|
122
|
+
const method = arrayMethodTarget(owner.callee);
|
|
123
|
+
const firstArgument = owner.arguments[0];
|
|
124
|
+
if (method === null || method.name !== "reduce" && method.name !== "reduceRight" || owner.arguments.length > 2 || firstArgument === undefined || unwrapArrayExpression(firstArgument) !== callback)
|
|
125
|
+
return null;
|
|
126
|
+
const firstParameter = callback.params[0];
|
|
127
|
+
const accumulator = firstParameter?.type === "AssignmentPattern" ? firstParameter.left : firstParameter;
|
|
128
|
+
if (accumulator?.type !== "Identifier")
|
|
129
|
+
return null;
|
|
130
|
+
return { callback, accumulator, initialValue: owner.arguments[1] };
|
|
131
|
+
}
|
|
132
|
+
parent = parent.parent;
|
|
133
|
+
}
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
function referencesAccumulator(sourceCode, node, accumulator, visited = new Set) {
|
|
137
|
+
const variable = resolveArrayBinding(sourceCode, node);
|
|
138
|
+
if (variable === null || visited.has(variable))
|
|
139
|
+
return false;
|
|
140
|
+
if (variable === accumulator)
|
|
141
|
+
return true;
|
|
142
|
+
visited.add(variable);
|
|
143
|
+
if (variable.references.some((reference) => reference.isWrite() && !reference.init))
|
|
144
|
+
return false;
|
|
145
|
+
for (const definition of variable.defs) {
|
|
146
|
+
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") {
|
|
147
|
+
return referencesAccumulator(sourceCode, definition.node.init, accumulator, visited);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return false;
|
|
151
|
+
}
|
|
152
|
+
function isGlobalCopyOwner(sourceCode, node, name) {
|
|
153
|
+
node = unwrapArrayExpression(node);
|
|
154
|
+
if (node.type !== "Identifier" || node.name !== name)
|
|
155
|
+
return false;
|
|
156
|
+
const variable = resolveArrayBinding(sourceCode, node);
|
|
157
|
+
return variable === null || variable.defs.length === 0;
|
|
158
|
+
}
|
|
159
|
+
var noReduceAccumulatorCopyRule = defineRule2({
|
|
160
|
+
meta: {
|
|
161
|
+
type: "problem",
|
|
162
|
+
docs: { description: "Disallow copying growing reducer accumulators with Object.assign, Array.from, or array copy methods." },
|
|
163
|
+
messages: {
|
|
164
|
+
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."
|
|
165
|
+
}
|
|
166
|
+
},
|
|
167
|
+
createOnce(context) {
|
|
168
|
+
return {
|
|
169
|
+
CallExpression(node) {
|
|
170
|
+
const method = arrayMethodTarget(node.callee);
|
|
171
|
+
if (method === null)
|
|
172
|
+
return;
|
|
173
|
+
const reducer = enclosingReducer(node);
|
|
174
|
+
if (reducer === null)
|
|
175
|
+
return;
|
|
176
|
+
const accumulator = context.sourceCode.getDeclaredVariables(reducer.callback).find((variable) => variable.identifiers.some((identifier) => identifier.start === reducer.accumulator.start));
|
|
177
|
+
if (accumulator === undefined)
|
|
178
|
+
return;
|
|
179
|
+
const isAccumulator = (expression) => referencesAccumulator(context.sourceCode, expression, accumulator);
|
|
180
|
+
let copiesAccumulator = false;
|
|
181
|
+
if (method.name === "assign" && isGlobalCopyOwner(context.sourceCode, method.object, "Object")) {
|
|
182
|
+
const target = node.arguments[0];
|
|
183
|
+
copiesAccumulator = target !== undefined && unwrapArrayExpression(target).type === "ObjectExpression" && node.arguments.slice(1).some(isAccumulator);
|
|
184
|
+
} else if (method.name === "from" && isGlobalCopyOwner(context.sourceCode, method.object, "Array")) {
|
|
185
|
+
const source = node.arguments[0];
|
|
186
|
+
copiesAccumulator = source !== undefined && isAccumulator(source);
|
|
187
|
+
} else if (["concat", "slice", "toSpliced", "toSorted", "toReversed", "with"].includes(method.name)) {
|
|
188
|
+
const initialValue = reducer.initialValue;
|
|
189
|
+
const arrayAccumulator = initialValue !== undefined && isKnownArrayExpression(context.sourceCode, initialValue);
|
|
190
|
+
copiesAccumulator = arrayAccumulator && isAccumulator(method.object);
|
|
191
|
+
}
|
|
192
|
+
if (copiesAccumulator)
|
|
193
|
+
context.report({ node, messageId: "accumulatorCopy" });
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
// vendor/anti-slop/src/rules/no-chained-type-assertions.ts
|
|
200
|
+
import { defineRule as defineRule3 } from "@oxlint/plugins";
|
|
6
201
|
function isTypeAssertionExpression(node) {
|
|
7
202
|
return node.type === "TSAsExpression" || node.type === "TSTypeAssertion";
|
|
8
203
|
}
|
|
@@ -37,7 +232,7 @@ function isForbiddenAssertionChain(node) {
|
|
|
37
232
|
}
|
|
38
233
|
return assertionCount > 1 && hasNonConstAssertion;
|
|
39
234
|
}
|
|
40
|
-
var noChainedTypeAssertionsRule =
|
|
235
|
+
var noChainedTypeAssertionsRule = defineRule3({
|
|
41
236
|
meta: {
|
|
42
237
|
type: "problem",
|
|
43
238
|
docs: {
|
|
@@ -61,7 +256,7 @@ var noChainedTypeAssertionsRule = defineRule({
|
|
|
61
256
|
});
|
|
62
257
|
|
|
63
258
|
// vendor/anti-slop/src/rules/no-conditional-empty-object-spread.ts
|
|
64
|
-
import { defineRule as
|
|
259
|
+
import { defineRule as defineRule4 } from "@oxlint/plugins";
|
|
65
260
|
function unwrapParentheses(node) {
|
|
66
261
|
let current = node;
|
|
67
262
|
while (current.type === "ParenthesizedExpression") {
|
|
@@ -76,7 +271,7 @@ function isConditionalEmptyObjectSpread(node) {
|
|
|
76
271
|
const conditional = unwrapParentheses(node);
|
|
77
272
|
return conditional.type === "ConditionalExpression" && (isEmptyObjectExpression(conditional.consequent) || isEmptyObjectExpression(conditional.alternate));
|
|
78
273
|
}
|
|
79
|
-
var noConditionalEmptyObjectSpreadRule =
|
|
274
|
+
var noConditionalEmptyObjectSpreadRule = defineRule4({
|
|
80
275
|
meta: {
|
|
81
276
|
type: "suggestion",
|
|
82
277
|
docs: {
|
|
@@ -100,7 +295,7 @@ var noConditionalEmptyObjectSpreadRule = defineRule2({
|
|
|
100
295
|
});
|
|
101
296
|
|
|
102
297
|
// vendor/anti-slop/src/rules/no-known-value-widening.ts
|
|
103
|
-
import { defineRule as
|
|
298
|
+
import { defineRule as defineRule5 } from "@oxlint/plugins";
|
|
104
299
|
|
|
105
300
|
// vendor/anti-slop/src/shared/lexical-type-parameters.ts
|
|
106
301
|
function isNode(value) {
|
|
@@ -503,9 +698,9 @@ function classifyWideningTarget(type, environment) {
|
|
|
503
698
|
if (alias === null)
|
|
504
699
|
return null;
|
|
505
700
|
if ((alias.typeParameters?.params.length ?? 0) > 0) {
|
|
506
|
-
const
|
|
507
|
-
const
|
|
508
|
-
return
|
|
701
|
+
const substitutions = aliasSubstitution(alias, unwrapped, new Map);
|
|
702
|
+
const resolved = substitutions === null ? null : classifyAliasBroadTarget(alias.typeAnnotation, environment, substitutions, new Set([name]));
|
|
703
|
+
return resolved?.kind === "open dictionary" ? { kind: "generic container" } : null;
|
|
509
704
|
}
|
|
510
705
|
const substitutions = aliasSubstitution(alias, unwrapped, new Map);
|
|
511
706
|
if (substitutions === null)
|
|
@@ -629,14 +824,7 @@ function functionParameterBindingName(parameter, sourceCode) {
|
|
|
629
824
|
return annotationStart === undefined ? sourceText : sourceText.slice(0, annotationStart - parameter.start).trimEnd();
|
|
630
825
|
}
|
|
631
826
|
|
|
632
|
-
// vendor/anti-slop/src/
|
|
633
|
-
function unwrapExpression(expression) {
|
|
634
|
-
let current = expression;
|
|
635
|
-
while (current.type === "ParenthesizedExpression" || current.type === "TSAsExpression" || current.type === "TSSatisfiesExpression" || current.type === "TSTypeAssertion" || current.type === "TSNonNullExpression") {
|
|
636
|
-
current = current.expression;
|
|
637
|
-
}
|
|
638
|
-
return current;
|
|
639
|
-
}
|
|
827
|
+
// vendor/anti-slop/src/shared/scope.ts
|
|
640
828
|
function resolveVariable(sourceCode, identifier) {
|
|
641
829
|
let scope = sourceCode.getScope(identifier);
|
|
642
830
|
while (scope !== null) {
|
|
@@ -647,6 +835,15 @@ function resolveVariable(sourceCode, identifier) {
|
|
|
647
835
|
}
|
|
648
836
|
return null;
|
|
649
837
|
}
|
|
838
|
+
|
|
839
|
+
// vendor/anti-slop/src/rules/no-known-value-widening.ts
|
|
840
|
+
function unwrapExpression(expression) {
|
|
841
|
+
let current = expression;
|
|
842
|
+
while (current.type === "ParenthesizedExpression" || current.type === "TSAsExpression" || current.type === "TSSatisfiesExpression" || current.type === "TSTypeAssertion" || current.type === "TSNonNullExpression") {
|
|
843
|
+
current = current.expression;
|
|
844
|
+
}
|
|
845
|
+
return current;
|
|
846
|
+
}
|
|
650
847
|
function variableDeclarator(variable) {
|
|
651
848
|
if (variable.defs.length !== 1)
|
|
652
849
|
return null;
|
|
@@ -799,7 +996,7 @@ function isDictionaryAccumulatorTarget(destination) {
|
|
|
799
996
|
function hasParentAssertion(node) {
|
|
800
997
|
return node.parent?.type === "TSAsExpression" || node.parent?.type === "TSTypeAssertion";
|
|
801
998
|
}
|
|
802
|
-
var noKnownValueWideningRule =
|
|
999
|
+
var noKnownValueWideningRule = defineRule5({
|
|
803
1000
|
meta: {
|
|
804
1001
|
type: "problem",
|
|
805
1002
|
docs: {
|
|
@@ -912,18 +1109,8 @@ var noKnownValueWideningRule = defineRule3({
|
|
|
912
1109
|
});
|
|
913
1110
|
|
|
914
1111
|
// vendor/anti-slop/src/rules/no-module-mocking.ts
|
|
915
|
-
import { defineRule as
|
|
1112
|
+
import { defineRule as defineRule6 } from "@oxlint/plugins";
|
|
916
1113
|
var moduleMockMethods = new Set(["doMock", "mock", "unstable_mockModule"]);
|
|
917
|
-
function resolveVariable2(sourceCode, identifier) {
|
|
918
|
-
let scope = sourceCode.getScope(identifier);
|
|
919
|
-
while (scope !== null) {
|
|
920
|
-
const variable = scope.set.get(identifier.name);
|
|
921
|
-
if (variable !== undefined)
|
|
922
|
-
return variable;
|
|
923
|
-
scope = scope.upper;
|
|
924
|
-
}
|
|
925
|
-
return null;
|
|
926
|
-
}
|
|
927
1114
|
function importedName(node) {
|
|
928
1115
|
if (node.type !== "ImportSpecifier")
|
|
929
1116
|
return null;
|
|
@@ -935,7 +1122,7 @@ function isTestFrameworkObject(sourceCode, expression) {
|
|
|
935
1122
|
if ((expression.name === "vi" || expression.name === "jest") && sourceCode.isGlobalReference(expression)) {
|
|
936
1123
|
return true;
|
|
937
1124
|
}
|
|
938
|
-
const variable =
|
|
1125
|
+
const variable = resolveVariable(sourceCode, expression);
|
|
939
1126
|
if (variable === null || variable.defs.length === 0) {
|
|
940
1127
|
return expression.name === "vi" || expression.name === "jest";
|
|
941
1128
|
}
|
|
@@ -957,7 +1144,7 @@ function moduleMockCall(sourceCode, callee) {
|
|
|
957
1144
|
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;
|
|
958
1145
|
return method !== null && moduleMockMethods.has(method);
|
|
959
1146
|
}
|
|
960
|
-
var noModuleMockingRule =
|
|
1147
|
+
var noModuleMockingRule = defineRule6({
|
|
961
1148
|
meta: {
|
|
962
1149
|
type: "problem",
|
|
963
1150
|
docs: {
|
|
@@ -981,8 +1168,8 @@ var noModuleMockingRule = defineRule4({
|
|
|
981
1168
|
});
|
|
982
1169
|
|
|
983
1170
|
// vendor/anti-slop/src/rules/no-object-parameters.ts
|
|
984
|
-
import { defineRule as
|
|
985
|
-
var noObjectParametersRule =
|
|
1171
|
+
import { defineRule as defineRule7 } from "@oxlint/plugins";
|
|
1172
|
+
var noObjectParametersRule = defineRule7({
|
|
986
1173
|
meta: {
|
|
987
1174
|
type: "problem",
|
|
988
1175
|
docs: {
|
|
@@ -1035,25 +1222,15 @@ var noObjectParametersRule = defineRule5({
|
|
|
1035
1222
|
});
|
|
1036
1223
|
|
|
1037
1224
|
// vendor/anti-slop/src/rules/no-reflect-apply.ts
|
|
1038
|
-
import { defineRule as
|
|
1225
|
+
import { defineRule as defineRule8 } from "@oxlint/plugins";
|
|
1039
1226
|
|
|
1040
1227
|
// vendor/anti-slop/src/shared/reflect-method.ts
|
|
1041
|
-
function resolveVariable3(sourceCode, identifier) {
|
|
1042
|
-
let scope = sourceCode.getScope(identifier);
|
|
1043
|
-
while (scope !== null) {
|
|
1044
|
-
const variable = scope.set.get(identifier.name);
|
|
1045
|
-
if (variable !== undefined)
|
|
1046
|
-
return variable;
|
|
1047
|
-
scope = scope.upper;
|
|
1048
|
-
}
|
|
1049
|
-
return null;
|
|
1050
|
-
}
|
|
1051
1228
|
function isGlobalReflect(sourceCode, expression) {
|
|
1052
1229
|
if (expression.type !== "Identifier" || expression.name !== "Reflect")
|
|
1053
1230
|
return false;
|
|
1054
1231
|
if (sourceCode.isGlobalReference(expression))
|
|
1055
1232
|
return true;
|
|
1056
|
-
const variable =
|
|
1233
|
+
const variable = resolveVariable(sourceCode, expression);
|
|
1057
1234
|
return variable === null || variable.defs.length === 0;
|
|
1058
1235
|
}
|
|
1059
1236
|
function isGlobalReflectMethodCall(sourceCode, callee, methodName) {
|
|
@@ -1066,7 +1243,7 @@ function isGlobalReflectMethodCall(sourceCode, callee, methodName) {
|
|
|
1066
1243
|
}
|
|
1067
1244
|
|
|
1068
1245
|
// vendor/anti-slop/src/rules/no-reflect-apply.ts
|
|
1069
|
-
var noReflectApplyRule =
|
|
1246
|
+
var noReflectApplyRule = defineRule8({
|
|
1070
1247
|
meta: {
|
|
1071
1248
|
type: "problem",
|
|
1072
1249
|
docs: {
|
|
@@ -1090,8 +1267,8 @@ var noReflectApplyRule = defineRule6({
|
|
|
1090
1267
|
});
|
|
1091
1268
|
|
|
1092
1269
|
// vendor/anti-slop/src/rules/no-reflect-get.ts
|
|
1093
|
-
import { defineRule as
|
|
1094
|
-
var noReflectGetRule =
|
|
1270
|
+
import { defineRule as defineRule9 } from "@oxlint/plugins";
|
|
1271
|
+
var noReflectGetRule = defineRule9({
|
|
1095
1272
|
meta: {
|
|
1096
1273
|
type: "problem",
|
|
1097
1274
|
docs: {
|
|
@@ -1115,7 +1292,7 @@ var noReflectGetRule = defineRule7({
|
|
|
1115
1292
|
});
|
|
1116
1293
|
|
|
1117
1294
|
// vendor/anti-slop/src/rules/no-runtime-typeof.ts
|
|
1118
|
-
import { defineRule as
|
|
1295
|
+
import { defineRule as defineRule10 } from "@oxlint/plugins";
|
|
1119
1296
|
function isRuntimeFunction(node) {
|
|
1120
1297
|
return node.type === "ArrowFunctionExpression" || node.type === "FunctionDeclaration" || node.type === "FunctionExpression";
|
|
1121
1298
|
}
|
|
@@ -1138,7 +1315,7 @@ function isExistenceProbe(node) {
|
|
|
1138
1315
|
const other = parent.left === node ? parent.right : parent.left;
|
|
1139
1316
|
return other.type === "Literal" && other.value === "undefined";
|
|
1140
1317
|
}
|
|
1141
|
-
var noRuntimeTypeofRule =
|
|
1318
|
+
var noRuntimeTypeofRule = defineRule10({
|
|
1142
1319
|
meta: {
|
|
1143
1320
|
type: "problem",
|
|
1144
1321
|
docs: {
|
|
@@ -1172,7 +1349,7 @@ var noRuntimeTypeofRule = defineRule8({
|
|
|
1172
1349
|
});
|
|
1173
1350
|
|
|
1174
1351
|
// vendor/anti-slop/src/rules/no-shape-in-symbol-names.ts
|
|
1175
|
-
import { defineRule as
|
|
1352
|
+
import { defineRule as defineRule11 } from "@oxlint/plugins";
|
|
1176
1353
|
var FORBIDDEN_SYMBOL_NAME = "shape";
|
|
1177
1354
|
function containsForbiddenSymbolName(name) {
|
|
1178
1355
|
return name.toLowerCase().includes(FORBIDDEN_SYMBOL_NAME);
|
|
@@ -1183,7 +1360,7 @@ function isBorrowedMemberName(node) {
|
|
|
1183
1360
|
return false;
|
|
1184
1361
|
return parent.property === node && parent.computed === false;
|
|
1185
1362
|
}
|
|
1186
|
-
var noForbiddenTermInSymbolNamesRule =
|
|
1363
|
+
var noForbiddenTermInSymbolNamesRule = defineRule11({
|
|
1187
1364
|
meta: {
|
|
1188
1365
|
type: "problem",
|
|
1189
1366
|
docs: {
|
|
@@ -1212,12 +1389,12 @@ var noForbiddenTermInSymbolNamesRule = defineRule9({
|
|
|
1212
1389
|
});
|
|
1213
1390
|
|
|
1214
1391
|
// vendor/anti-slop/src/rules/no-unknown-parameters.ts
|
|
1215
|
-
import { defineRule as
|
|
1392
|
+
import { defineRule as defineRule12 } from "@oxlint/plugins";
|
|
1216
1393
|
function isTypePredicateSubject(owner, parameterName) {
|
|
1217
1394
|
const predicate = owner.returnType?.typeAnnotation;
|
|
1218
1395
|
return predicate?.type === "TSTypePredicate" && predicate.parameterName.type === "Identifier" && predicate.parameterName.name === parameterName;
|
|
1219
1396
|
}
|
|
1220
|
-
var noUnknownParametersRule =
|
|
1397
|
+
var noUnknownParametersRule = defineRule12({
|
|
1221
1398
|
meta: {
|
|
1222
1399
|
type: "problem",
|
|
1223
1400
|
docs: {
|
|
@@ -1261,8 +1438,8 @@ var noUnknownParametersRule = defineRule10({
|
|
|
1261
1438
|
});
|
|
1262
1439
|
|
|
1263
1440
|
// vendor/anti-slop/src/rules/no-unknown-returns.ts
|
|
1264
|
-
import { defineRule as
|
|
1265
|
-
var noUnknownReturnsRule =
|
|
1441
|
+
import { defineRule as defineRule13 } from "@oxlint/plugins";
|
|
1442
|
+
var noUnknownReturnsRule = defineRule13({
|
|
1266
1443
|
meta: {
|
|
1267
1444
|
type: "problem",
|
|
1268
1445
|
docs: {
|
|
@@ -1315,8 +1492,8 @@ var noUnknownReturnsRule = defineRule11({
|
|
|
1315
1492
|
});
|
|
1316
1493
|
|
|
1317
1494
|
// vendor/anti-slop/src/rules/no-unknown-type-aliases.ts
|
|
1318
|
-
import { defineRule as
|
|
1319
|
-
var noUnknownTypeAliasesRule =
|
|
1495
|
+
import { defineRule as defineRule14 } from "@oxlint/plugins";
|
|
1496
|
+
var noUnknownTypeAliasesRule = defineRule14({
|
|
1320
1497
|
meta: {
|
|
1321
1498
|
type: "problem",
|
|
1322
1499
|
docs: {
|
|
@@ -1354,7 +1531,7 @@ var noUnknownTypeAliasesRule = defineRule12({
|
|
|
1354
1531
|
});
|
|
1355
1532
|
|
|
1356
1533
|
// vendor/anti-slop/src/rules/no-unsafe-dictionary-type.ts
|
|
1357
|
-
import { defineRule as
|
|
1534
|
+
import { defineRule as defineRule15 } from "@oxlint/plugins";
|
|
1358
1535
|
var typeNodeKinds = new Set([
|
|
1359
1536
|
"JSDocNonNullableType",
|
|
1360
1537
|
"JSDocNullableType",
|
|
@@ -1441,7 +1618,7 @@ function shouldReportType(node, environment) {
|
|
|
1441
1618
|
}
|
|
1442
1619
|
return true;
|
|
1443
1620
|
}
|
|
1444
|
-
var noUnsafeDictionaryTypeRule =
|
|
1621
|
+
var noUnsafeDictionaryTypeRule = defineRule15({
|
|
1445
1622
|
meta: {
|
|
1446
1623
|
type: "problem",
|
|
1447
1624
|
docs: {
|
|
@@ -1483,7 +1660,7 @@ var noUnsafeDictionaryTypeRule = defineRule13({
|
|
|
1483
1660
|
});
|
|
1484
1661
|
|
|
1485
1662
|
// vendor/anti-slop/src/rules/no-widen-then-assert.ts
|
|
1486
|
-
import { defineRule as
|
|
1663
|
+
import { defineRule as defineRule16 } from "@oxlint/plugins";
|
|
1487
1664
|
var functionBoundaryTypes = new Set([
|
|
1488
1665
|
"ArrowFunctionExpression",
|
|
1489
1666
|
"FunctionDeclaration",
|
|
@@ -1679,7 +1856,7 @@ function assertionIsNarrower(sourceText, broadKind, evidence, assertedType) {
|
|
|
1679
1856
|
return isDefinitelyObjectType(assertedType);
|
|
1680
1857
|
return isDefinitelyNarrowerRecordType(assertedType);
|
|
1681
1858
|
}
|
|
1682
|
-
var noWidenThenAssertRule =
|
|
1859
|
+
var noWidenThenAssertRule = defineRule16({
|
|
1683
1860
|
meta: {
|
|
1684
1861
|
type: "problem",
|
|
1685
1862
|
docs: {
|
|
@@ -1718,8 +1895,530 @@ var noWidenThenAssertRule = defineRule14({
|
|
|
1718
1895
|
}
|
|
1719
1896
|
});
|
|
1720
1897
|
|
|
1898
|
+
// vendor/anti-slop/src/vendor/eslint-stylistic/padding-line-ast.ts
|
|
1899
|
+
var LINEBREAKS = new Set([`\r
|
|
1900
|
+
`, "\r", `
|
|
1901
|
+
`, "\u2028", "\u2029"]);
|
|
1902
|
+
var isClosingBraceToken = (token) => token.type === "Punctuator" && token.value === "}";
|
|
1903
|
+
var isSemicolonToken = (token) => token.type === "Punctuator" && token.value === ";";
|
|
1904
|
+
var isNotSemicolonToken = (token) => !isSemicolonToken(token);
|
|
1905
|
+
var isTokenOnSameLine = (left, right) => left.loc.end.line === right.loc.start.line;
|
|
1906
|
+
var isFunction = (node) => node.type === "FunctionDeclaration" || node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression";
|
|
1907
|
+
var isSingleLine = (node) => node.loc.start.line === node.loc.end.line;
|
|
1908
|
+
var skipChainExpression = (node) => node.type === "ChainExpression" ? node.expression : node;
|
|
1909
|
+
var isTopLevelExpressionStatement = (node) => node.type === "ExpressionStatement" && (node.parent.type === "Program" || node.parent.type === "BlockStatement" && isFunction(node.parent.parent));
|
|
1910
|
+
function isParenthesized(node, sourceCode) {
|
|
1911
|
+
const before = sourceCode.getTokenBefore(node);
|
|
1912
|
+
const after = sourceCode.getTokenAfter(node);
|
|
1913
|
+
return before?.value === "(" && after?.value === ")";
|
|
1914
|
+
}
|
|
1915
|
+
|
|
1916
|
+
// vendor/anti-slop/src/vendor/eslint-stylistic/padding-line-between-statements.ts
|
|
1917
|
+
var CJS_EXPORT = /^(?:module\s*\.\s*)?exports(?:\s*\.|\s*\[|$)/u;
|
|
1918
|
+
var CJS_IMPORT = /^require\(/u;
|
|
1919
|
+
var LT = `[${Array.from(LINEBREAKS).join("")}]`;
|
|
1920
|
+
var PADDING_LINE_SEQUENCE = new RegExp(String.raw`^(\s*?${LT})\s*${LT}(\s*;?)$`, "u");
|
|
1921
|
+
function isSelectorOption(option) {
|
|
1922
|
+
return typeof option === "object" && !Array.isArray(option);
|
|
1923
|
+
}
|
|
1924
|
+
function newKeywordTester(type, keyword) {
|
|
1925
|
+
return {
|
|
1926
|
+
test(node, sourceCode) {
|
|
1927
|
+
const isSameKeyword = sourceCode.getFirstToken(node)?.value === keyword;
|
|
1928
|
+
const isSameType = Array.isArray(type) ? type.includes(node.type) : type === node.type;
|
|
1929
|
+
return isSameKeyword && isSameType;
|
|
1930
|
+
}
|
|
1931
|
+
};
|
|
1932
|
+
}
|
|
1933
|
+
function newNodeTypeTester(type) {
|
|
1934
|
+
return {
|
|
1935
|
+
test: (node) => node.type === type
|
|
1936
|
+
};
|
|
1937
|
+
}
|
|
1938
|
+
function isIIFEStatement(node) {
|
|
1939
|
+
if (node.type === "ExpressionStatement") {
|
|
1940
|
+
let expression = skipChainExpression(node.expression);
|
|
1941
|
+
if (expression.type === "UnaryExpression")
|
|
1942
|
+
expression = skipChainExpression(expression.argument);
|
|
1943
|
+
if (expression.type === "CallExpression") {
|
|
1944
|
+
let node = expression.callee;
|
|
1945
|
+
while (node.type === "SequenceExpression") {
|
|
1946
|
+
const lastExpression = node.expressions.at(-1);
|
|
1947
|
+
if (lastExpression === undefined)
|
|
1948
|
+
throw new Error("Padding rule invariant: sequence expression is empty");
|
|
1949
|
+
node = lastExpression;
|
|
1950
|
+
}
|
|
1951
|
+
return isFunction(node);
|
|
1952
|
+
}
|
|
1953
|
+
}
|
|
1954
|
+
return false;
|
|
1955
|
+
}
|
|
1956
|
+
function isCJSRequire(node) {
|
|
1957
|
+
if (node.type === "VariableDeclaration") {
|
|
1958
|
+
const declaration = node.declarations[0];
|
|
1959
|
+
if (declaration?.init) {
|
|
1960
|
+
let call = declaration?.init;
|
|
1961
|
+
while (call.type === "MemberExpression")
|
|
1962
|
+
call = call.object;
|
|
1963
|
+
if (call.type === "CallExpression" && call.callee.type === "Identifier") {
|
|
1964
|
+
return call.callee.name === "require";
|
|
1965
|
+
}
|
|
1966
|
+
}
|
|
1967
|
+
}
|
|
1968
|
+
return false;
|
|
1969
|
+
}
|
|
1970
|
+
function isBlockLikeStatement(node, sourceCode) {
|
|
1971
|
+
if (node.type === "DoWhileStatement" && node.body.type === "BlockStatement") {
|
|
1972
|
+
return true;
|
|
1973
|
+
}
|
|
1974
|
+
if (isIIFEStatement(node))
|
|
1975
|
+
return true;
|
|
1976
|
+
const lastToken = sourceCode.getLastToken(node, isNotSemicolonToken);
|
|
1977
|
+
const belongingNode = lastToken && isClosingBraceToken(lastToken) ? sourceCode.getNodeByRangeIndex(lastToken.range[0]) : null;
|
|
1978
|
+
return !!belongingNode && (belongingNode.type === "BlockStatement" || belongingNode.type === "SwitchStatement");
|
|
1979
|
+
}
|
|
1980
|
+
function isDirective(node, sourceCode) {
|
|
1981
|
+
return isTopLevelExpressionStatement(node) && node.expression.type === "Literal" && typeof node.expression.value === "string" && !isParenthesized(node.expression, sourceCode);
|
|
1982
|
+
}
|
|
1983
|
+
function isDirectivePrologue(node, sourceCode) {
|
|
1984
|
+
if (isDirective(node, sourceCode) && node.parent && "body" in node.parent && Array.isArray(node.parent.body)) {
|
|
1985
|
+
for (const sibling of node.parent.body) {
|
|
1986
|
+
if (sibling === node)
|
|
1987
|
+
break;
|
|
1988
|
+
if (!isDirective(sibling, sourceCode))
|
|
1989
|
+
return false;
|
|
1990
|
+
}
|
|
1991
|
+
return true;
|
|
1992
|
+
}
|
|
1993
|
+
return false;
|
|
1994
|
+
}
|
|
1995
|
+
function isCJSExport(node) {
|
|
1996
|
+
if (node.type === "ExpressionStatement") {
|
|
1997
|
+
const expression = node.expression;
|
|
1998
|
+
if (expression.type === "AssignmentExpression") {
|
|
1999
|
+
let left = expression.left;
|
|
2000
|
+
if (left.type === "MemberExpression") {
|
|
2001
|
+
while (left.object.type === "MemberExpression")
|
|
2002
|
+
left = left.object;
|
|
2003
|
+
return left.object.type === "Identifier" && (left.object.name === "exports" || left.object.name === "module" && left.property.type === "Identifier" && left.property.name === "exports");
|
|
2004
|
+
}
|
|
2005
|
+
}
|
|
2006
|
+
}
|
|
2007
|
+
return false;
|
|
2008
|
+
}
|
|
2009
|
+
function isExpression(node, sourceCode) {
|
|
2010
|
+
return node.type === "ExpressionStatement" && !isDirectivePrologue(node, sourceCode);
|
|
2011
|
+
}
|
|
2012
|
+
function getActualLastToken(node, sourceCode) {
|
|
2013
|
+
const semiToken = sourceCode.getLastToken(node);
|
|
2014
|
+
const prevToken = sourceCode.getTokenBefore(semiToken);
|
|
2015
|
+
const nextToken = sourceCode.getTokenAfter(semiToken);
|
|
2016
|
+
const isSemicolonLessStyle = prevToken && nextToken && prevToken.range[0] >= node.range[0] && isSemicolonToken(semiToken) && !isTokenOnSameLine(prevToken, semiToken) && isTokenOnSameLine(semiToken, nextToken);
|
|
2017
|
+
return isSemicolonLessStyle ? prevToken : semiToken;
|
|
2018
|
+
}
|
|
2019
|
+
function replacerToRemovePaddingLines(_, trailingSpaces, indentSpaces) {
|
|
2020
|
+
return trailingSpaces + indentSpaces;
|
|
2021
|
+
}
|
|
2022
|
+
function getReportLoc(node, sourceCode) {
|
|
2023
|
+
if (isSingleLine(node))
|
|
2024
|
+
return node.loc;
|
|
2025
|
+
const line = node.loc.start.line;
|
|
2026
|
+
const sourceLine = sourceCode.lines[line - 1];
|
|
2027
|
+
if (sourceLine === undefined)
|
|
2028
|
+
throw new Error("Padding rule invariant: statement source line is missing");
|
|
2029
|
+
return {
|
|
2030
|
+
start: node.loc.start,
|
|
2031
|
+
end: {
|
|
2032
|
+
line,
|
|
2033
|
+
column: sourceLine.length
|
|
2034
|
+
}
|
|
2035
|
+
};
|
|
2036
|
+
}
|
|
2037
|
+
function verifyForAny() {}
|
|
2038
|
+
function verifyForNever(context, _, nextNode, paddingLines) {
|
|
2039
|
+
if (paddingLines.length === 0)
|
|
2040
|
+
return;
|
|
2041
|
+
context.report({
|
|
2042
|
+
node: nextNode,
|
|
2043
|
+
messageId: "unexpectedBlankLine",
|
|
2044
|
+
loc: getReportLoc(nextNode, context.sourceCode),
|
|
2045
|
+
fix(fixer) {
|
|
2046
|
+
if (paddingLines.length >= 2)
|
|
2047
|
+
return null;
|
|
2048
|
+
const paddingPair = paddingLines[0];
|
|
2049
|
+
if (paddingPair === undefined)
|
|
2050
|
+
throw new Error("Padding rule invariant: reported padding pair is missing");
|
|
2051
|
+
const [prevToken, nextToken] = paddingPair;
|
|
2052
|
+
const start = prevToken.range[1];
|
|
2053
|
+
const end = nextToken.range[0];
|
|
2054
|
+
const text = context.sourceCode.text.slice(start, end).replace(PADDING_LINE_SEQUENCE, replacerToRemovePaddingLines);
|
|
2055
|
+
return fixer.replaceTextRange([start, end], text);
|
|
2056
|
+
}
|
|
2057
|
+
});
|
|
2058
|
+
}
|
|
2059
|
+
function verifyForAlways(context, prevNode, nextNode, paddingLines) {
|
|
2060
|
+
if (paddingLines.length > 0)
|
|
2061
|
+
return;
|
|
2062
|
+
context.report({
|
|
2063
|
+
node: nextNode,
|
|
2064
|
+
messageId: "expectedBlankLine",
|
|
2065
|
+
loc: getReportLoc(nextNode, context.sourceCode),
|
|
2066
|
+
fix(fixer) {
|
|
2067
|
+
const sourceCode = context.sourceCode;
|
|
2068
|
+
let prevToken = getActualLastToken(prevNode, sourceCode);
|
|
2069
|
+
const nextToken = sourceCode.getFirstTokenBetween(prevToken, nextNode, {
|
|
2070
|
+
includeComments: true,
|
|
2071
|
+
filter(token) {
|
|
2072
|
+
if (isTokenOnSameLine(prevToken, token)) {
|
|
2073
|
+
prevToken = token;
|
|
2074
|
+
return false;
|
|
2075
|
+
}
|
|
2076
|
+
return true;
|
|
2077
|
+
}
|
|
2078
|
+
}) || nextNode;
|
|
2079
|
+
const insertText = isTokenOnSameLine(prevToken, nextToken) ? `
|
|
2080
|
+
|
|
2081
|
+
` : `
|
|
2082
|
+
`;
|
|
2083
|
+
return fixer.insertTextAfter(prevToken, insertText);
|
|
2084
|
+
}
|
|
2085
|
+
});
|
|
2086
|
+
}
|
|
2087
|
+
var PaddingTypes = {
|
|
2088
|
+
any: { verify: verifyForAny },
|
|
2089
|
+
never: { verify: verifyForNever },
|
|
2090
|
+
always: { verify: verifyForAlways }
|
|
2091
|
+
};
|
|
2092
|
+
var MaybeMultilineStatementType = {
|
|
2093
|
+
"block-like": { test: isBlockLikeStatement },
|
|
2094
|
+
expression: { test: isExpression },
|
|
2095
|
+
return: newKeywordTester("ReturnStatement", "return"),
|
|
2096
|
+
export: newKeywordTester([
|
|
2097
|
+
"ExportAllDeclaration",
|
|
2098
|
+
"ExportDefaultDeclaration",
|
|
2099
|
+
"ExportNamedDeclaration"
|
|
2100
|
+
], "export"),
|
|
2101
|
+
var: newKeywordTester("VariableDeclaration", "var"),
|
|
2102
|
+
let: newKeywordTester("VariableDeclaration", "let"),
|
|
2103
|
+
const: newKeywordTester("VariableDeclaration", "const"),
|
|
2104
|
+
using: {
|
|
2105
|
+
test: (node) => node.type === "VariableDeclaration" && (node.kind === "using" || node.kind === "await using")
|
|
2106
|
+
},
|
|
2107
|
+
type: newKeywordTester("TSTypeAliasDeclaration", "type")
|
|
2108
|
+
};
|
|
2109
|
+
var StatementTypes = {
|
|
2110
|
+
"*": { test: () => true },
|
|
2111
|
+
exports: { test: isCJSExport },
|
|
2112
|
+
require: { test: isCJSRequire },
|
|
2113
|
+
directive: { test: isDirectivePrologue },
|
|
2114
|
+
iife: { test: isIIFEStatement },
|
|
2115
|
+
block: newNodeTypeTester("BlockStatement"),
|
|
2116
|
+
empty: newNodeTypeTester("EmptyStatement"),
|
|
2117
|
+
function: newNodeTypeTester("FunctionDeclaration"),
|
|
2118
|
+
"ts-method": newNodeTypeTester("TSMethodSignature"),
|
|
2119
|
+
break: newKeywordTester("BreakStatement", "break"),
|
|
2120
|
+
case: newKeywordTester("SwitchCase", "case"),
|
|
2121
|
+
class: newKeywordTester("ClassDeclaration", "class"),
|
|
2122
|
+
continue: newKeywordTester("ContinueStatement", "continue"),
|
|
2123
|
+
debugger: newKeywordTester("DebuggerStatement", "debugger"),
|
|
2124
|
+
default: newKeywordTester(["SwitchCase", "ExportDefaultDeclaration"], "default"),
|
|
2125
|
+
do: newKeywordTester("DoWhileStatement", "do"),
|
|
2126
|
+
for: newKeywordTester([
|
|
2127
|
+
"ForStatement",
|
|
2128
|
+
"ForInStatement",
|
|
2129
|
+
"ForOfStatement"
|
|
2130
|
+
], "for"),
|
|
2131
|
+
if: newKeywordTester("IfStatement", "if"),
|
|
2132
|
+
import: newKeywordTester("ImportDeclaration", "import"),
|
|
2133
|
+
switch: newKeywordTester("SwitchStatement", "switch"),
|
|
2134
|
+
throw: newKeywordTester("ThrowStatement", "throw"),
|
|
2135
|
+
try: newKeywordTester("TryStatement", "try"),
|
|
2136
|
+
while: newKeywordTester(["WhileStatement", "DoWhileStatement"], "while"),
|
|
2137
|
+
with: newKeywordTester("WithStatement", "with"),
|
|
2138
|
+
"cjs-export": {
|
|
2139
|
+
test: (node, sourceCode) => node.type === "ExpressionStatement" && node.expression.type === "AssignmentExpression" && CJS_EXPORT.test(sourceCode.getText(node.expression.left))
|
|
2140
|
+
},
|
|
2141
|
+
"cjs-import": {
|
|
2142
|
+
test: (node, sourceCode) => node.type === "VariableDeclaration" && node.declarations.length > 0 && node.declarations[0]?.init != null && CJS_IMPORT.test(sourceCode.getText(node.declarations[0].init))
|
|
2143
|
+
},
|
|
2144
|
+
enum: newKeywordTester("TSEnumDeclaration", "enum"),
|
|
2145
|
+
interface: newKeywordTester("TSInterfaceDeclaration", "interface"),
|
|
2146
|
+
"function-overload": newNodeTypeTester("TSDeclareFunction"),
|
|
2147
|
+
...Object.fromEntries(Object.entries(MaybeMultilineStatementType).flatMap(([key, value]) => [
|
|
2148
|
+
[key, value],
|
|
2149
|
+
[
|
|
2150
|
+
`singleline-${key}`,
|
|
2151
|
+
{
|
|
2152
|
+
...value,
|
|
2153
|
+
test: (node, sourceCode) => value.test(node, sourceCode) && isSingleLine(node)
|
|
2154
|
+
}
|
|
2155
|
+
],
|
|
2156
|
+
[
|
|
2157
|
+
`multiline-${key}`,
|
|
2158
|
+
{
|
|
2159
|
+
...value,
|
|
2160
|
+
test: (node, sourceCode) => value.test(node, sourceCode) && !isSingleLine(node)
|
|
2161
|
+
}
|
|
2162
|
+
]
|
|
2163
|
+
]))
|
|
2164
|
+
};
|
|
2165
|
+
function createPaddingLineRule(options) {
|
|
2166
|
+
return {
|
|
2167
|
+
meta: {
|
|
2168
|
+
type: "layout",
|
|
2169
|
+
docs: {
|
|
2170
|
+
description: "Require or disallow padding lines between statements"
|
|
2171
|
+
},
|
|
2172
|
+
fixable: "whitespace",
|
|
2173
|
+
hasSuggestions: false,
|
|
2174
|
+
schema: {
|
|
2175
|
+
$defs: {
|
|
2176
|
+
paddingType: {
|
|
2177
|
+
type: "string",
|
|
2178
|
+
enum: Object.keys(PaddingTypes)
|
|
2179
|
+
},
|
|
2180
|
+
statementType: {
|
|
2181
|
+
type: "string",
|
|
2182
|
+
enum: Object.keys(StatementTypes)
|
|
2183
|
+
},
|
|
2184
|
+
selectorOption: {
|
|
2185
|
+
type: "object",
|
|
2186
|
+
properties: {
|
|
2187
|
+
selector: {
|
|
2188
|
+
type: "string"
|
|
2189
|
+
},
|
|
2190
|
+
lineMode: {
|
|
2191
|
+
type: "string",
|
|
2192
|
+
enum: ["any", "singleline", "multiline"]
|
|
2193
|
+
}
|
|
2194
|
+
},
|
|
2195
|
+
required: ["selector"],
|
|
2196
|
+
additionalProperties: false
|
|
2197
|
+
},
|
|
2198
|
+
statementMatcher: {
|
|
2199
|
+
anyOf: [
|
|
2200
|
+
{ $ref: "#/$defs/statementType" },
|
|
2201
|
+
{ $ref: "#/$defs/selectorOption" }
|
|
2202
|
+
]
|
|
2203
|
+
},
|
|
2204
|
+
statementOption: {
|
|
2205
|
+
anyOf: [
|
|
2206
|
+
{ $ref: "#/$defs/statementMatcher" },
|
|
2207
|
+
{
|
|
2208
|
+
type: "array",
|
|
2209
|
+
items: { $ref: "#/$defs/statementMatcher" },
|
|
2210
|
+
minItems: 1,
|
|
2211
|
+
uniqueItems: true,
|
|
2212
|
+
additionalItems: false
|
|
2213
|
+
}
|
|
2214
|
+
]
|
|
2215
|
+
}
|
|
2216
|
+
},
|
|
2217
|
+
type: "array",
|
|
2218
|
+
additionalItems: false,
|
|
2219
|
+
items: {
|
|
2220
|
+
type: "object",
|
|
2221
|
+
properties: {
|
|
2222
|
+
blankLine: { $ref: "#/$defs/paddingType" },
|
|
2223
|
+
prev: { $ref: "#/$defs/statementOption" },
|
|
2224
|
+
next: { $ref: "#/$defs/statementOption" }
|
|
2225
|
+
},
|
|
2226
|
+
additionalProperties: false,
|
|
2227
|
+
required: ["blankLine", "prev", "next"]
|
|
2228
|
+
}
|
|
2229
|
+
},
|
|
2230
|
+
messages: {
|
|
2231
|
+
unexpectedBlankLine: "Unexpected blank line before this statement.",
|
|
2232
|
+
expectedBlankLine: "Expected blank line before this statement."
|
|
2233
|
+
}
|
|
2234
|
+
},
|
|
2235
|
+
create(context) {
|
|
2236
|
+
const sourceCode = context.sourceCode;
|
|
2237
|
+
const selectorMatchedNodes = new Map;
|
|
2238
|
+
const pendingPairs = [];
|
|
2239
|
+
function collectSelectorOption(option) {
|
|
2240
|
+
if (Array.isArray(option)) {
|
|
2241
|
+
for (const item of option)
|
|
2242
|
+
collectSelectorOption(item);
|
|
2243
|
+
return;
|
|
2244
|
+
}
|
|
2245
|
+
if (!isSelectorOption(option))
|
|
2246
|
+
return;
|
|
2247
|
+
selectorMatchedNodes.set(option.selector, new Set);
|
|
2248
|
+
}
|
|
2249
|
+
for (const configure of options) {
|
|
2250
|
+
collectSelectorOption(configure.prev);
|
|
2251
|
+
collectSelectorOption(configure.next);
|
|
2252
|
+
}
|
|
2253
|
+
let scopeInfo = null;
|
|
2254
|
+
function enterScope() {
|
|
2255
|
+
scopeInfo = {
|
|
2256
|
+
upper: scopeInfo,
|
|
2257
|
+
prevNode: null
|
|
2258
|
+
};
|
|
2259
|
+
}
|
|
2260
|
+
function exitScope() {
|
|
2261
|
+
if (scopeInfo)
|
|
2262
|
+
scopeInfo = scopeInfo.upper;
|
|
2263
|
+
}
|
|
2264
|
+
function match(node, type) {
|
|
2265
|
+
let innerStatementNode = node;
|
|
2266
|
+
while (innerStatementNode.type === "LabeledStatement")
|
|
2267
|
+
innerStatementNode = innerStatementNode.body;
|
|
2268
|
+
if (Array.isArray(type))
|
|
2269
|
+
return type.some(match.bind(null, innerStatementNode));
|
|
2270
|
+
if (isSelectorOption(type)) {
|
|
2271
|
+
const matchedNodes = selectorMatchedNodes.get(type.selector);
|
|
2272
|
+
if (!matchedNodes?.has(innerStatementNode))
|
|
2273
|
+
return false;
|
|
2274
|
+
const lineMode = type.lineMode;
|
|
2275
|
+
if (lineMode === "singleline")
|
|
2276
|
+
return isSingleLine(innerStatementNode);
|
|
2277
|
+
else if (lineMode === "multiline")
|
|
2278
|
+
return !isSingleLine(innerStatementNode);
|
|
2279
|
+
return true;
|
|
2280
|
+
} else {
|
|
2281
|
+
const statementType = StatementTypes[type];
|
|
2282
|
+
if (statementType === undefined)
|
|
2283
|
+
throw new Error(`Padding rule invariant: unsupported statement type ${type}`);
|
|
2284
|
+
return statementType.test(innerStatementNode, sourceCode);
|
|
2285
|
+
}
|
|
2286
|
+
}
|
|
2287
|
+
function getPaddingType(prevNode, nextNode) {
|
|
2288
|
+
for (let i = options.length - 1;i >= 0; --i) {
|
|
2289
|
+
const configure = options[i];
|
|
2290
|
+
if (configure === undefined)
|
|
2291
|
+
throw new Error("Padding rule invariant: configuration entry is missing");
|
|
2292
|
+
if (match(prevNode, configure.prev) && match(nextNode, configure.next)) {
|
|
2293
|
+
return PaddingTypes[configure.blankLine];
|
|
2294
|
+
}
|
|
2295
|
+
}
|
|
2296
|
+
return PaddingTypes.any;
|
|
2297
|
+
}
|
|
2298
|
+
function getPaddingLineSequences(prevNode, nextNode) {
|
|
2299
|
+
const pairs = [];
|
|
2300
|
+
let prevToken = getActualLastToken(prevNode, sourceCode);
|
|
2301
|
+
if (nextNode.loc.start.line - prevToken.loc.end.line >= 2) {
|
|
2302
|
+
do {
|
|
2303
|
+
const token = sourceCode.getTokenAfter(prevToken, {
|
|
2304
|
+
includeComments: true
|
|
2305
|
+
});
|
|
2306
|
+
if (token.loc.start.line - prevToken.loc.end.line >= 2)
|
|
2307
|
+
pairs.push([prevToken, token]);
|
|
2308
|
+
prevToken = token;
|
|
2309
|
+
} while (prevToken.range[0] < nextNode.range[0]);
|
|
2310
|
+
}
|
|
2311
|
+
return pairs;
|
|
2312
|
+
}
|
|
2313
|
+
function verify(node) {
|
|
2314
|
+
if (!node.parent || ![
|
|
2315
|
+
"BlockStatement",
|
|
2316
|
+
"Program",
|
|
2317
|
+
"StaticBlock",
|
|
2318
|
+
"SwitchCase",
|
|
2319
|
+
"SwitchStatement",
|
|
2320
|
+
"TSInterfaceBody",
|
|
2321
|
+
"TSModuleBlock",
|
|
2322
|
+
"TSTypeLiteral"
|
|
2323
|
+
].includes(node.parent.type)) {
|
|
2324
|
+
return;
|
|
2325
|
+
}
|
|
2326
|
+
const prevNode = scopeInfo.prevNode;
|
|
2327
|
+
if (prevNode)
|
|
2328
|
+
pendingPairs.push({ prevNode, nextNode: node });
|
|
2329
|
+
scopeInfo.prevNode = node;
|
|
2330
|
+
}
|
|
2331
|
+
function verifyPendingPairs() {
|
|
2332
|
+
for (const { prevNode, nextNode } of pendingPairs) {
|
|
2333
|
+
const type = getPaddingType(prevNode, nextNode);
|
|
2334
|
+
const paddingLines = getPaddingLineSequences(prevNode, nextNode);
|
|
2335
|
+
type.verify(context, prevNode, nextNode, paddingLines);
|
|
2336
|
+
}
|
|
2337
|
+
}
|
|
2338
|
+
function verifyThenEnterScope(node) {
|
|
2339
|
+
verify(node);
|
|
2340
|
+
enterScope();
|
|
2341
|
+
}
|
|
2342
|
+
const selectorMatchListeners = Object.fromEntries(Array.from(selectorMatchedNodes.keys(), (selector) => [
|
|
2343
|
+
selector,
|
|
2344
|
+
(node) => {
|
|
2345
|
+
selectorMatchedNodes.get(selector)?.add(node);
|
|
2346
|
+
}
|
|
2347
|
+
]));
|
|
2348
|
+
return {
|
|
2349
|
+
Program: enterScope,
|
|
2350
|
+
"Program:exit": () => {
|
|
2351
|
+
verifyPendingPairs();
|
|
2352
|
+
exitScope();
|
|
2353
|
+
},
|
|
2354
|
+
BlockStatement: enterScope,
|
|
2355
|
+
"BlockStatement:exit": exitScope,
|
|
2356
|
+
SwitchStatement: enterScope,
|
|
2357
|
+
"SwitchStatement:exit": exitScope,
|
|
2358
|
+
SwitchCase: verifyThenEnterScope,
|
|
2359
|
+
"SwitchCase:exit": exitScope,
|
|
2360
|
+
StaticBlock: enterScope,
|
|
2361
|
+
"StaticBlock:exit": exitScope,
|
|
2362
|
+
TSInterfaceBody: enterScope,
|
|
2363
|
+
"TSInterfaceBody:exit": exitScope,
|
|
2364
|
+
TSModuleBlock: enterScope,
|
|
2365
|
+
"TSModuleBlock:exit": exitScope,
|
|
2366
|
+
TSTypeLiteral: enterScope,
|
|
2367
|
+
"TSTypeLiteral:exit": exitScope,
|
|
2368
|
+
TSDeclareFunction: verifyThenEnterScope,
|
|
2369
|
+
"TSDeclareFunction:exit": exitScope,
|
|
2370
|
+
TSMethodSignature: verifyThenEnterScope,
|
|
2371
|
+
"TSMethodSignature:exit": exitScope,
|
|
2372
|
+
":statement": verify,
|
|
2373
|
+
...selectorMatchListeners
|
|
2374
|
+
};
|
|
2375
|
+
}
|
|
2376
|
+
};
|
|
2377
|
+
}
|
|
2378
|
+
|
|
2379
|
+
// vendor/anti-slop/src/rules/require-readable-spacing.ts
|
|
2380
|
+
var paddingRule = createPaddingLineRule([
|
|
2381
|
+
{ blankLine: "always", prev: "import", next: "*" },
|
|
2382
|
+
{ blankLine: "always", prev: "*", next: { selector: "Program > :not(ImportDeclaration)" } },
|
|
2383
|
+
{ blankLine: "always", prev: { selector: "Program > :not(ImportDeclaration)" }, next: "*" },
|
|
2384
|
+
{ blankLine: "always", prev: "*", next: ["function", "class", "interface", "type"] },
|
|
2385
|
+
{ blankLine: "always", prev: ["function", "class", "interface", "type"], next: "*" },
|
|
2386
|
+
{
|
|
2387
|
+
blankLine: "always",
|
|
2388
|
+
prev: "*",
|
|
2389
|
+
next: ["multiline-const", "multiline-let", "multiline-var", "multiline-using"]
|
|
2390
|
+
},
|
|
2391
|
+
{
|
|
2392
|
+
blankLine: "always",
|
|
2393
|
+
prev: ["multiline-const", "multiline-let", "multiline-var", "multiline-using"],
|
|
2394
|
+
next: "*"
|
|
2395
|
+
},
|
|
2396
|
+
{ blankLine: "always", prev: "*", next: ["return", "if", "switch", "try", "for", "while", "do"] },
|
|
2397
|
+
{ blankLine: "always", prev: "block-like", next: "*" },
|
|
2398
|
+
{ blankLine: "any", prev: "import", next: "import" },
|
|
2399
|
+
{
|
|
2400
|
+
blankLine: "any",
|
|
2401
|
+
prev: {
|
|
2402
|
+
selector: ':matches(TSDeclareFunction, ExportNamedDeclaration[declaration.type="TSDeclareFunction"])'
|
|
2403
|
+
},
|
|
2404
|
+
next: {
|
|
2405
|
+
selector: ':matches(TSDeclareFunction, FunctionDeclaration, ExportNamedDeclaration[declaration.type="TSDeclareFunction"], ExportNamedDeclaration[declaration.type="FunctionDeclaration"])'
|
|
2406
|
+
}
|
|
2407
|
+
}
|
|
2408
|
+
]);
|
|
2409
|
+
var requireReadableSpacingRule = {
|
|
2410
|
+
...paddingRule,
|
|
2411
|
+
meta: {
|
|
2412
|
+
...paddingRule.meta,
|
|
2413
|
+
docs: {
|
|
2414
|
+
description: "Require readable spacing between declarations and logical statement groups."
|
|
2415
|
+
},
|
|
2416
|
+
schema: []
|
|
2417
|
+
}
|
|
2418
|
+
};
|
|
2419
|
+
|
|
1721
2420
|
// vendor/anti-slop/src/rules/require-safety-comment-for-type-assertion.ts
|
|
1722
|
-
import { defineRule as
|
|
2421
|
+
import { defineRule as defineRule17 } from "@oxlint/plugins";
|
|
1723
2422
|
var DEFAULT_SAFETY_MARKERS = ["SAFETY"];
|
|
1724
2423
|
var commentOwnerKinds = new Set([
|
|
1725
2424
|
"ExpressionStatement",
|
|
@@ -1762,7 +2461,7 @@ function hasSafetyComment(sourceCode, node, pattern) {
|
|
|
1762
2461
|
current = current.parent;
|
|
1763
2462
|
}
|
|
1764
2463
|
}
|
|
1765
|
-
var requireSafetyCommentForTypeAssertionRule =
|
|
2464
|
+
var requireSafetyCommentForTypeAssertionRule = defineRule17({
|
|
1766
2465
|
meta: {
|
|
1767
2466
|
type: "problem",
|
|
1768
2467
|
docs: {
|
|
@@ -1815,6 +2514,8 @@ var requireSafetyCommentForTypeAssertionRule = defineRule15({
|
|
|
1815
2514
|
var antiSlopPlugin = eslintCompatPlugin({
|
|
1816
2515
|
meta: { name: "anti-slop" },
|
|
1817
2516
|
rules: {
|
|
2517
|
+
"no-array-filter-map": noArrayFilterMapRule,
|
|
2518
|
+
"no-reduce-accumulator-copy": noReduceAccumulatorCopyRule,
|
|
1818
2519
|
"no-chained-type-assertions": noChainedTypeAssertionsRule,
|
|
1819
2520
|
"no-conditional-empty-object-spread": noConditionalEmptyObjectSpreadRule,
|
|
1820
2521
|
"no-known-value-widening": noKnownValueWideningRule,
|
|
@@ -1829,6 +2530,7 @@ var antiSlopPlugin = eslintCompatPlugin({
|
|
|
1829
2530
|
"no-unknown-returns": noUnknownReturnsRule,
|
|
1830
2531
|
"no-unknown-type-aliases": noUnknownTypeAliasesRule,
|
|
1831
2532
|
"no-widen-then-assert": noWidenThenAssertRule,
|
|
2533
|
+
"require-readable-spacing": requireReadableSpacingRule,
|
|
1832
2534
|
"require-safety-comment-for-type-assertion": requireSafetyCommentForTypeAssertionRule
|
|
1833
2535
|
}
|
|
1834
2536
|
});
|