@nekoyasuii/config 0.1.5 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-fqcw0kzp.js → chunk-5vqtdgjy.js} +134 -10
- package/dist/{chunk-0xdbbpn5.js → chunk-cpyyjvfv.js} +2 -2
- package/dist/{chunk-08m6971b.js → chunk-k5zpegn9.js} +5 -5
- package/dist/{chunk-41590bpf.js → chunk-tvk9tq03.js} +2 -2
- package/dist/tools/oxfmt/index.js +3 -4
- package/dist/tools/oxlint/config/core/index.js +4 -5
- package/dist/tools/oxlint/config/index.d.ts +47 -45
- package/dist/tools/oxlint/config/index.js +11 -20
- package/dist/tools/oxlint/config/js-plugins/index.d.ts +270 -64
- package/dist/tools/oxlint/config/js-plugins/index.js +6 -7
- package/dist/tools/oxlint/config/react/index.js +3 -4
- package/dist/tools/oxlint/config/remix/index.js +0 -2
- package/dist/tools/oxlint/config/tanstack/index.js +0 -2
- package/dist/tools/oxlint/config/tanstack/js-plugins/index.d.ts +4 -4
- package/dist/tools/oxlint/config/tanstack/js-plugins/index.js +0 -2
- package/dist/tools/oxlint/config/{anti-slop/plugin.js → vendors/anti-slop.js} +717 -35
- package/dist/tools/oxlint/config/{no-comment-slop/plugin.d.ts → vendors/no-comment-slop.d.ts} +34 -0
- package/dist/tools/oxlint/config/{no-comment-slop/plugin.js → vendors/no-comment-slop.js} +72 -8
- package/dist/tools/oxlint/config/vendors/shadcn.d.ts +41 -0
- package/dist/tools/oxlint/config/vendors/shadcn.js +7159 -0
- package/dist/tools/oxlint/rules/index.js +7 -9
- package/dist/tools/shared/ignores.js +3 -4
- package/package.json +3 -13
- package/dist/chunk-5wgwscd0.js +0 -4
- package/dist/chunk-97s6xvc6.js +0 -32
- package/dist/chunk-c8jq73qx.js +0 -38
- package/dist/tools/oxlint/config/anti-slop/index.d.ts +0 -42
- package/dist/tools/oxlint/config/anti-slop/index.js +0 -7
- package/dist/tools/oxlint/config/no-comment-slop/index.d.ts +0 -19
- package/dist/tools/oxlint/config/no-comment-slop/index.js +0 -7
- /package/dist/tools/oxlint/config/{anti-slop/plugin.d.ts → vendors/anti-slop.d.ts} +0 -0
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
// tools/oxlint/config/anti-slop/plugin.ts
|
|
1
|
+
// tools/oxlint/config/vendors/anti-slop.ts
|
|
4
2
|
function defineRule(rule) {
|
|
5
3
|
return rule;
|
|
6
4
|
}
|
|
@@ -167,6 +165,191 @@ function createContextAndVisitor(rule, afterHooksState) {
|
|
|
167
165
|
setupAfterHook
|
|
168
166
|
};
|
|
169
167
|
}
|
|
168
|
+
function unwrapArrayExpression(node) {
|
|
169
|
+
while (node.type === "ParenthesizedExpression" || node.type === "ChainExpression" || node.type === "TSAsExpression" || node.type === "TSTypeAssertion" || node.type === "TSNonNullExpression" || node.type === "TSSatisfiesExpression") {
|
|
170
|
+
node = node.expression;
|
|
171
|
+
}
|
|
172
|
+
return node;
|
|
173
|
+
}
|
|
174
|
+
function resolveArrayBinding(sourceCode, node) {
|
|
175
|
+
node = unwrapArrayExpression(node);
|
|
176
|
+
if (node.type !== "Identifier")
|
|
177
|
+
return null;
|
|
178
|
+
let scope = sourceCode.getScope(node);
|
|
179
|
+
while (scope !== null) {
|
|
180
|
+
const variable = scope.set.get(node.name);
|
|
181
|
+
if (variable !== undefined)
|
|
182
|
+
return variable;
|
|
183
|
+
scope = scope.upper;
|
|
184
|
+
}
|
|
185
|
+
return null;
|
|
186
|
+
}
|
|
187
|
+
function arrayMethodTarget(node) {
|
|
188
|
+
node = unwrapArrayExpression(node);
|
|
189
|
+
if (node.type !== "MemberExpression")
|
|
190
|
+
return null;
|
|
191
|
+
const property = node.property;
|
|
192
|
+
if (!node.computed && property.type === "Identifier") {
|
|
193
|
+
return { name: property.name, object: node.object };
|
|
194
|
+
}
|
|
195
|
+
if (node.computed && property.type === "Literal" && typeof property.value === "string") {
|
|
196
|
+
return { name: property.value, object: node.object };
|
|
197
|
+
}
|
|
198
|
+
return null;
|
|
199
|
+
}
|
|
200
|
+
function isArrayAnnotation(type) {
|
|
201
|
+
if (type.type === "TSArrayType" || type.type === "TSTupleType")
|
|
202
|
+
return true;
|
|
203
|
+
if (type.type === "TSParenthesizedType")
|
|
204
|
+
return isArrayAnnotation(type.typeAnnotation);
|
|
205
|
+
if (type.type === "TSTypeOperator" && type.operator === "readonly") {
|
|
206
|
+
return isArrayAnnotation(type.typeAnnotation);
|
|
207
|
+
}
|
|
208
|
+
return type.type === "TSTypeReference" && type.typeName.type === "Identifier" && (type.typeName.name === "Array" || type.typeName.name === "ReadonlyArray");
|
|
209
|
+
}
|
|
210
|
+
function isKnownArrayExpression(sourceCode, node, visited = new Set) {
|
|
211
|
+
node = unwrapArrayExpression(node);
|
|
212
|
+
if (node.type === "ArrayExpression")
|
|
213
|
+
return true;
|
|
214
|
+
if (node.type === "CallExpression") {
|
|
215
|
+
const method = arrayMethodTarget(node.callee);
|
|
216
|
+
return method !== null && ["map", "filter", "flatMap", "slice", "concat", "toSorted", "toReversed", "toSpliced"].includes(method.name) && isKnownArrayExpression(sourceCode, method.object, visited);
|
|
217
|
+
}
|
|
218
|
+
if (node.type !== "Identifier")
|
|
219
|
+
return false;
|
|
220
|
+
const variable = resolveArrayBinding(sourceCode, node);
|
|
221
|
+
if (variable === null || visited.has(variable))
|
|
222
|
+
return false;
|
|
223
|
+
visited.add(variable);
|
|
224
|
+
if (variable.references.some((reference) => reference.isWrite() && !reference.init))
|
|
225
|
+
return false;
|
|
226
|
+
for (const identifier of variable.identifiers) {
|
|
227
|
+
const annotation = identifier.typeAnnotation?.typeAnnotation;
|
|
228
|
+
if (annotation !== undefined)
|
|
229
|
+
return isArrayAnnotation(annotation);
|
|
230
|
+
}
|
|
231
|
+
for (const definition of variable.defs) {
|
|
232
|
+
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") {
|
|
233
|
+
return isKnownArrayExpression(sourceCode, definition.node.init, visited);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return false;
|
|
237
|
+
}
|
|
238
|
+
var noArrayFilterMapRule = defineRule({
|
|
239
|
+
meta: {
|
|
240
|
+
type: "suggestion",
|
|
241
|
+
docs: { description: "Disallow adjacent array filter/map passes in favor of lazy iterator helpers or a single transformation." },
|
|
242
|
+
messages: {
|
|
243
|
+
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."
|
|
244
|
+
}
|
|
245
|
+
},
|
|
246
|
+
createOnce(context) {
|
|
247
|
+
return {
|
|
248
|
+
CallExpression(node) {
|
|
249
|
+
const outer = arrayMethodTarget(node.callee);
|
|
250
|
+
if (outer === null || outer.name !== "map" && outer.name !== "filter")
|
|
251
|
+
return;
|
|
252
|
+
const innerCall = unwrapArrayExpression(outer.object);
|
|
253
|
+
if (innerCall.type !== "CallExpression")
|
|
254
|
+
return;
|
|
255
|
+
const inner = arrayMethodTarget(innerCall.callee);
|
|
256
|
+
if (inner === null || inner.name !== (outer.name === "map" ? "filter" : "map"))
|
|
257
|
+
return;
|
|
258
|
+
if (!isKnownArrayExpression(context.sourceCode, inner.object))
|
|
259
|
+
return;
|
|
260
|
+
context.report({ node, messageId: "arrayFilterMap", data: { first: inner.name, second: outer.name } });
|
|
261
|
+
}
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
});
|
|
265
|
+
function enclosingReducer(node) {
|
|
266
|
+
let parent = node.parent;
|
|
267
|
+
while (parent !== null) {
|
|
268
|
+
if (parent.type === "FunctionDeclaration")
|
|
269
|
+
return null;
|
|
270
|
+
if (parent.type === "ArrowFunctionExpression" || parent.type === "FunctionExpression") {
|
|
271
|
+
const callback = parent;
|
|
272
|
+
let owner = callback.parent;
|
|
273
|
+
while (owner !== null && unwrapArrayExpression(owner) === callback)
|
|
274
|
+
owner = owner.parent;
|
|
275
|
+
if (owner?.type !== "CallExpression")
|
|
276
|
+
return null;
|
|
277
|
+
const method = arrayMethodTarget(owner.callee);
|
|
278
|
+
const firstArgument = owner.arguments[0];
|
|
279
|
+
if (method === null || method.name !== "reduce" && method.name !== "reduceRight" || owner.arguments.length > 2 || firstArgument === undefined || unwrapArrayExpression(firstArgument) !== callback)
|
|
280
|
+
return null;
|
|
281
|
+
const firstParameter = callback.params[0];
|
|
282
|
+
const accumulator = firstParameter?.type === "AssignmentPattern" ? firstParameter.left : firstParameter;
|
|
283
|
+
if (accumulator?.type !== "Identifier")
|
|
284
|
+
return null;
|
|
285
|
+
return { callback, accumulator, initialValue: owner.arguments[1] };
|
|
286
|
+
}
|
|
287
|
+
parent = parent.parent;
|
|
288
|
+
}
|
|
289
|
+
return null;
|
|
290
|
+
}
|
|
291
|
+
function referencesAccumulator(sourceCode, node, accumulator, visited = new Set) {
|
|
292
|
+
const variable = resolveArrayBinding(sourceCode, node);
|
|
293
|
+
if (variable === null || visited.has(variable))
|
|
294
|
+
return false;
|
|
295
|
+
if (variable === accumulator)
|
|
296
|
+
return true;
|
|
297
|
+
visited.add(variable);
|
|
298
|
+
if (variable.references.some((reference) => reference.isWrite() && !reference.init))
|
|
299
|
+
return false;
|
|
300
|
+
for (const definition of variable.defs) {
|
|
301
|
+
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") {
|
|
302
|
+
return referencesAccumulator(sourceCode, definition.node.init, accumulator, visited);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
return false;
|
|
306
|
+
}
|
|
307
|
+
function isGlobalCopyOwner(sourceCode, node, name) {
|
|
308
|
+
node = unwrapArrayExpression(node);
|
|
309
|
+
if (node.type !== "Identifier" || node.name !== name)
|
|
310
|
+
return false;
|
|
311
|
+
const variable = resolveArrayBinding(sourceCode, node);
|
|
312
|
+
return variable === null || variable.defs.length === 0;
|
|
313
|
+
}
|
|
314
|
+
var noReduceAccumulatorCopyRule = defineRule({
|
|
315
|
+
meta: {
|
|
316
|
+
type: "problem",
|
|
317
|
+
docs: { description: "Disallow copying growing reducer accumulators with Object.assign, Array.from, or array copy methods." },
|
|
318
|
+
messages: {
|
|
319
|
+
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."
|
|
320
|
+
}
|
|
321
|
+
},
|
|
322
|
+
createOnce(context) {
|
|
323
|
+
return {
|
|
324
|
+
CallExpression(node) {
|
|
325
|
+
const method = arrayMethodTarget(node.callee);
|
|
326
|
+
if (method === null)
|
|
327
|
+
return;
|
|
328
|
+
const reducer = enclosingReducer(node);
|
|
329
|
+
if (reducer === null)
|
|
330
|
+
return;
|
|
331
|
+
const accumulator = context.sourceCode.getDeclaredVariables(reducer.callback).find((variable) => variable.identifiers.some((identifier) => identifier.start === reducer.accumulator.start));
|
|
332
|
+
if (accumulator === undefined)
|
|
333
|
+
return;
|
|
334
|
+
const isAccumulator = (expression) => referencesAccumulator(context.sourceCode, expression, accumulator);
|
|
335
|
+
let copiesAccumulator = false;
|
|
336
|
+
if (method.name === "assign" && isGlobalCopyOwner(context.sourceCode, method.object, "Object")) {
|
|
337
|
+
const target = node.arguments[0];
|
|
338
|
+
copiesAccumulator = target !== undefined && unwrapArrayExpression(target).type === "ObjectExpression" && node.arguments.slice(1).some(isAccumulator);
|
|
339
|
+
} else if (method.name === "from" && isGlobalCopyOwner(context.sourceCode, method.object, "Array")) {
|
|
340
|
+
const source = node.arguments[0];
|
|
341
|
+
copiesAccumulator = source !== undefined && isAccumulator(source);
|
|
342
|
+
} else if (["concat", "slice", "toSpliced", "toSorted", "toReversed", "with"].includes(method.name)) {
|
|
343
|
+
const initialValue = reducer.initialValue;
|
|
344
|
+
const arrayAccumulator = initialValue !== undefined && isKnownArrayExpression(context.sourceCode, initialValue);
|
|
345
|
+
copiesAccumulator = arrayAccumulator && isAccumulator(method.object);
|
|
346
|
+
}
|
|
347
|
+
if (copiesAccumulator)
|
|
348
|
+
context.report({ node, messageId: "accumulatorCopy" });
|
|
349
|
+
}
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
});
|
|
170
353
|
function isTypeAssertionExpression(node) {
|
|
171
354
|
return node.type === "TSAsExpression" || node.type === "TSTypeAssertion";
|
|
172
355
|
}
|
|
@@ -655,9 +838,9 @@ function classifyWideningTarget(type, environment) {
|
|
|
655
838
|
if (alias === null)
|
|
656
839
|
return null;
|
|
657
840
|
if ((alias.typeParameters?.params.length ?? 0) > 0) {
|
|
658
|
-
const
|
|
659
|
-
const
|
|
660
|
-
return
|
|
841
|
+
const substitutions = aliasSubstitution(alias, unwrapped, new Map);
|
|
842
|
+
const resolved = substitutions === null ? null : classifyAliasBroadTarget(alias.typeAnnotation, environment, substitutions, new Set([name]));
|
|
843
|
+
return resolved?.kind === "open dictionary" ? { kind: "generic container" } : null;
|
|
661
844
|
}
|
|
662
845
|
const substitutions = aliasSubstitution(alias, unwrapped, new Map);
|
|
663
846
|
if (substitutions === null)
|
|
@@ -778,13 +961,6 @@ function functionParameterBindingName(parameter, sourceCode) {
|
|
|
778
961
|
const annotationStart = parameter.typeAnnotation?.start;
|
|
779
962
|
return annotationStart === undefined ? sourceText : sourceText.slice(0, annotationStart - parameter.start).trimEnd();
|
|
780
963
|
}
|
|
781
|
-
function unwrapExpression(expression) {
|
|
782
|
-
let current = expression;
|
|
783
|
-
while (current.type === "ParenthesizedExpression" || current.type === "TSAsExpression" || current.type === "TSSatisfiesExpression" || current.type === "TSTypeAssertion" || current.type === "TSNonNullExpression") {
|
|
784
|
-
current = current.expression;
|
|
785
|
-
}
|
|
786
|
-
return current;
|
|
787
|
-
}
|
|
788
964
|
function resolveVariable(sourceCode, identifier) {
|
|
789
965
|
let scope = sourceCode.getScope(identifier);
|
|
790
966
|
while (scope !== null) {
|
|
@@ -795,6 +971,13 @@ function resolveVariable(sourceCode, identifier) {
|
|
|
795
971
|
}
|
|
796
972
|
return null;
|
|
797
973
|
}
|
|
974
|
+
function unwrapExpression(expression) {
|
|
975
|
+
let current = expression;
|
|
976
|
+
while (current.type === "ParenthesizedExpression" || current.type === "TSAsExpression" || current.type === "TSSatisfiesExpression" || current.type === "TSTypeAssertion" || current.type === "TSNonNullExpression") {
|
|
977
|
+
current = current.expression;
|
|
978
|
+
}
|
|
979
|
+
return current;
|
|
980
|
+
}
|
|
798
981
|
function variableDeclarator(variable) {
|
|
799
982
|
if (variable.defs.length !== 1)
|
|
800
983
|
return null;
|
|
@@ -1059,16 +1242,6 @@ var noKnownValueWideningRule = defineRule({
|
|
|
1059
1242
|
}
|
|
1060
1243
|
});
|
|
1061
1244
|
var moduleMockMethods = new Set(["doMock", "mock", "unstable_mockModule"]);
|
|
1062
|
-
function resolveVariable2(sourceCode, identifier) {
|
|
1063
|
-
let scope = sourceCode.getScope(identifier);
|
|
1064
|
-
while (scope !== null) {
|
|
1065
|
-
const variable = scope.set.get(identifier.name);
|
|
1066
|
-
if (variable !== undefined)
|
|
1067
|
-
return variable;
|
|
1068
|
-
scope = scope.upper;
|
|
1069
|
-
}
|
|
1070
|
-
return null;
|
|
1071
|
-
}
|
|
1072
1245
|
function importedName(node) {
|
|
1073
1246
|
if (node.type !== "ImportSpecifier")
|
|
1074
1247
|
return null;
|
|
@@ -1080,7 +1253,7 @@ function isTestFrameworkObject(sourceCode, expression) {
|
|
|
1080
1253
|
if ((expression.name === "vi" || expression.name === "jest") && sourceCode.isGlobalReference(expression)) {
|
|
1081
1254
|
return true;
|
|
1082
1255
|
}
|
|
1083
|
-
const variable =
|
|
1256
|
+
const variable = resolveVariable(sourceCode, expression);
|
|
1084
1257
|
if (variable === null || variable.defs.length === 0) {
|
|
1085
1258
|
return expression.name === "vi" || expression.name === "jest";
|
|
1086
1259
|
}
|
|
@@ -1175,22 +1348,12 @@ var noObjectParametersRule = defineRule({
|
|
|
1175
1348
|
};
|
|
1176
1349
|
}
|
|
1177
1350
|
});
|
|
1178
|
-
function resolveVariable3(sourceCode, identifier) {
|
|
1179
|
-
let scope = sourceCode.getScope(identifier);
|
|
1180
|
-
while (scope !== null) {
|
|
1181
|
-
const variable = scope.set.get(identifier.name);
|
|
1182
|
-
if (variable !== undefined)
|
|
1183
|
-
return variable;
|
|
1184
|
-
scope = scope.upper;
|
|
1185
|
-
}
|
|
1186
|
-
return null;
|
|
1187
|
-
}
|
|
1188
1351
|
function isGlobalReflect(sourceCode, expression) {
|
|
1189
1352
|
if (expression.type !== "Identifier" || expression.name !== "Reflect")
|
|
1190
1353
|
return false;
|
|
1191
1354
|
if (sourceCode.isGlobalReference(expression))
|
|
1192
1355
|
return true;
|
|
1193
|
-
const variable =
|
|
1356
|
+
const variable = resolveVariable(sourceCode, expression);
|
|
1194
1357
|
return variable === null || variable.defs.length === 0;
|
|
1195
1358
|
}
|
|
1196
1359
|
function isGlobalReflectMethodCall(sourceCode, callee, methodName) {
|
|
@@ -1828,6 +1991,522 @@ var noWidenThenAssertRule = defineRule({
|
|
|
1828
1991
|
};
|
|
1829
1992
|
}
|
|
1830
1993
|
});
|
|
1994
|
+
var LINEBREAKS = new Set([`\r
|
|
1995
|
+
`, "\r", `
|
|
1996
|
+
`, "\u2028", "\u2029"]);
|
|
1997
|
+
var isClosingBraceToken = (token) => token.type === "Punctuator" && token.value === "}";
|
|
1998
|
+
var isSemicolonToken = (token) => token.type === "Punctuator" && token.value === ";";
|
|
1999
|
+
var isNotSemicolonToken = (token) => !isSemicolonToken(token);
|
|
2000
|
+
var isTokenOnSameLine = (left, right) => left.loc.end.line === right.loc.start.line;
|
|
2001
|
+
var isFunction = (node) => node.type === "FunctionDeclaration" || node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression";
|
|
2002
|
+
var isSingleLine = (node) => node.loc.start.line === node.loc.end.line;
|
|
2003
|
+
var skipChainExpression = (node) => node.type === "ChainExpression" ? node.expression : node;
|
|
2004
|
+
var isTopLevelExpressionStatement = (node) => node.type === "ExpressionStatement" && (node.parent.type === "Program" || node.parent.type === "BlockStatement" && isFunction(node.parent.parent));
|
|
2005
|
+
function isParenthesized(node, sourceCode) {
|
|
2006
|
+
const before = sourceCode.getTokenBefore(node);
|
|
2007
|
+
const after = sourceCode.getTokenAfter(node);
|
|
2008
|
+
return before?.value === "(" && after?.value === ")";
|
|
2009
|
+
}
|
|
2010
|
+
var CJS_EXPORT = /^(?:module\s*\.\s*)?exports(?:\s*\.|\s*\[|$)/u;
|
|
2011
|
+
var CJS_IMPORT = /^require\(/u;
|
|
2012
|
+
var LT = `[${Array.from(LINEBREAKS).join("")}]`;
|
|
2013
|
+
var PADDING_LINE_SEQUENCE = new RegExp(String.raw`^(\s*?${LT})\s*${LT}(\s*;?)$`, "u");
|
|
2014
|
+
function isSelectorOption(option) {
|
|
2015
|
+
return typeof option === "object" && !Array.isArray(option);
|
|
2016
|
+
}
|
|
2017
|
+
function newKeywordTester(type, keyword) {
|
|
2018
|
+
return {
|
|
2019
|
+
test(node, sourceCode) {
|
|
2020
|
+
const isSameKeyword = sourceCode.getFirstToken(node)?.value === keyword;
|
|
2021
|
+
const isSameType = Array.isArray(type) ? type.includes(node.type) : type === node.type;
|
|
2022
|
+
return isSameKeyword && isSameType;
|
|
2023
|
+
}
|
|
2024
|
+
};
|
|
2025
|
+
}
|
|
2026
|
+
function newNodeTypeTester(type) {
|
|
2027
|
+
return {
|
|
2028
|
+
test: (node) => node.type === type
|
|
2029
|
+
};
|
|
2030
|
+
}
|
|
2031
|
+
function isIIFEStatement(node) {
|
|
2032
|
+
if (node.type === "ExpressionStatement") {
|
|
2033
|
+
let expression = skipChainExpression(node.expression);
|
|
2034
|
+
if (expression.type === "UnaryExpression")
|
|
2035
|
+
expression = skipChainExpression(expression.argument);
|
|
2036
|
+
if (expression.type === "CallExpression") {
|
|
2037
|
+
let node = expression.callee;
|
|
2038
|
+
while (node.type === "SequenceExpression") {
|
|
2039
|
+
const lastExpression = node.expressions.at(-1);
|
|
2040
|
+
if (lastExpression === undefined)
|
|
2041
|
+
throw new Error("Padding rule invariant: sequence expression is empty");
|
|
2042
|
+
node = lastExpression;
|
|
2043
|
+
}
|
|
2044
|
+
return isFunction(node);
|
|
2045
|
+
}
|
|
2046
|
+
}
|
|
2047
|
+
return false;
|
|
2048
|
+
}
|
|
2049
|
+
function isCJSRequire(node) {
|
|
2050
|
+
if (node.type === "VariableDeclaration") {
|
|
2051
|
+
const declaration = node.declarations[0];
|
|
2052
|
+
if (declaration?.init) {
|
|
2053
|
+
let call = declaration?.init;
|
|
2054
|
+
while (call.type === "MemberExpression")
|
|
2055
|
+
call = call.object;
|
|
2056
|
+
if (call.type === "CallExpression" && call.callee.type === "Identifier") {
|
|
2057
|
+
return call.callee.name === "require";
|
|
2058
|
+
}
|
|
2059
|
+
}
|
|
2060
|
+
}
|
|
2061
|
+
return false;
|
|
2062
|
+
}
|
|
2063
|
+
function isBlockLikeStatement(node, sourceCode) {
|
|
2064
|
+
if (node.type === "DoWhileStatement" && node.body.type === "BlockStatement") {
|
|
2065
|
+
return true;
|
|
2066
|
+
}
|
|
2067
|
+
if (isIIFEStatement(node))
|
|
2068
|
+
return true;
|
|
2069
|
+
const lastToken = sourceCode.getLastToken(node, isNotSemicolonToken);
|
|
2070
|
+
const belongingNode = lastToken && isClosingBraceToken(lastToken) ? sourceCode.getNodeByRangeIndex(lastToken.range[0]) : null;
|
|
2071
|
+
return !!belongingNode && (belongingNode.type === "BlockStatement" || belongingNode.type === "SwitchStatement");
|
|
2072
|
+
}
|
|
2073
|
+
function isDirective(node, sourceCode) {
|
|
2074
|
+
return isTopLevelExpressionStatement(node) && node.expression.type === "Literal" && typeof node.expression.value === "string" && !isParenthesized(node.expression, sourceCode);
|
|
2075
|
+
}
|
|
2076
|
+
function isDirectivePrologue(node, sourceCode) {
|
|
2077
|
+
if (isDirective(node, sourceCode) && node.parent && "body" in node.parent && Array.isArray(node.parent.body)) {
|
|
2078
|
+
for (const sibling of node.parent.body) {
|
|
2079
|
+
if (sibling === node)
|
|
2080
|
+
break;
|
|
2081
|
+
if (!isDirective(sibling, sourceCode))
|
|
2082
|
+
return false;
|
|
2083
|
+
}
|
|
2084
|
+
return true;
|
|
2085
|
+
}
|
|
2086
|
+
return false;
|
|
2087
|
+
}
|
|
2088
|
+
function isCJSExport(node) {
|
|
2089
|
+
if (node.type === "ExpressionStatement") {
|
|
2090
|
+
const expression = node.expression;
|
|
2091
|
+
if (expression.type === "AssignmentExpression") {
|
|
2092
|
+
let left = expression.left;
|
|
2093
|
+
if (left.type === "MemberExpression") {
|
|
2094
|
+
while (left.object.type === "MemberExpression")
|
|
2095
|
+
left = left.object;
|
|
2096
|
+
return left.object.type === "Identifier" && (left.object.name === "exports" || left.object.name === "module" && left.property.type === "Identifier" && left.property.name === "exports");
|
|
2097
|
+
}
|
|
2098
|
+
}
|
|
2099
|
+
}
|
|
2100
|
+
return false;
|
|
2101
|
+
}
|
|
2102
|
+
function isExpression(node, sourceCode) {
|
|
2103
|
+
return node.type === "ExpressionStatement" && !isDirectivePrologue(node, sourceCode);
|
|
2104
|
+
}
|
|
2105
|
+
function getActualLastToken(node, sourceCode) {
|
|
2106
|
+
const semiToken = sourceCode.getLastToken(node);
|
|
2107
|
+
const prevToken = sourceCode.getTokenBefore(semiToken);
|
|
2108
|
+
const nextToken = sourceCode.getTokenAfter(semiToken);
|
|
2109
|
+
const isSemicolonLessStyle = prevToken && nextToken && prevToken.range[0] >= node.range[0] && isSemicolonToken(semiToken) && !isTokenOnSameLine(prevToken, semiToken) && isTokenOnSameLine(semiToken, nextToken);
|
|
2110
|
+
return isSemicolonLessStyle ? prevToken : semiToken;
|
|
2111
|
+
}
|
|
2112
|
+
function replacerToRemovePaddingLines(_, trailingSpaces, indentSpaces) {
|
|
2113
|
+
return trailingSpaces + indentSpaces;
|
|
2114
|
+
}
|
|
2115
|
+
function getReportLoc(node, sourceCode) {
|
|
2116
|
+
if (isSingleLine(node))
|
|
2117
|
+
return node.loc;
|
|
2118
|
+
const line = node.loc.start.line;
|
|
2119
|
+
const sourceLine = sourceCode.lines[line - 1];
|
|
2120
|
+
if (sourceLine === undefined)
|
|
2121
|
+
throw new Error("Padding rule invariant: statement source line is missing");
|
|
2122
|
+
return {
|
|
2123
|
+
start: node.loc.start,
|
|
2124
|
+
end: {
|
|
2125
|
+
line,
|
|
2126
|
+
column: sourceLine.length
|
|
2127
|
+
}
|
|
2128
|
+
};
|
|
2129
|
+
}
|
|
2130
|
+
function verifyForAny() {}
|
|
2131
|
+
function verifyForNever(context, _, nextNode, paddingLines) {
|
|
2132
|
+
if (paddingLines.length === 0)
|
|
2133
|
+
return;
|
|
2134
|
+
context.report({
|
|
2135
|
+
node: nextNode,
|
|
2136
|
+
messageId: "unexpectedBlankLine",
|
|
2137
|
+
loc: getReportLoc(nextNode, context.sourceCode),
|
|
2138
|
+
fix(fixer) {
|
|
2139
|
+
if (paddingLines.length >= 2)
|
|
2140
|
+
return null;
|
|
2141
|
+
const paddingPair = paddingLines[0];
|
|
2142
|
+
if (paddingPair === undefined)
|
|
2143
|
+
throw new Error("Padding rule invariant: reported padding pair is missing");
|
|
2144
|
+
const [prevToken, nextToken] = paddingPair;
|
|
2145
|
+
const start = prevToken.range[1];
|
|
2146
|
+
const end = nextToken.range[0];
|
|
2147
|
+
const text = context.sourceCode.text.slice(start, end).replace(PADDING_LINE_SEQUENCE, replacerToRemovePaddingLines);
|
|
2148
|
+
return fixer.replaceTextRange([start, end], text);
|
|
2149
|
+
}
|
|
2150
|
+
});
|
|
2151
|
+
}
|
|
2152
|
+
function verifyForAlways(context, prevNode, nextNode, paddingLines) {
|
|
2153
|
+
if (paddingLines.length > 0)
|
|
2154
|
+
return;
|
|
2155
|
+
context.report({
|
|
2156
|
+
node: nextNode,
|
|
2157
|
+
messageId: "expectedBlankLine",
|
|
2158
|
+
loc: getReportLoc(nextNode, context.sourceCode),
|
|
2159
|
+
fix(fixer) {
|
|
2160
|
+
const sourceCode = context.sourceCode;
|
|
2161
|
+
let prevToken = getActualLastToken(prevNode, sourceCode);
|
|
2162
|
+
const nextToken = sourceCode.getFirstTokenBetween(prevToken, nextNode, {
|
|
2163
|
+
includeComments: true,
|
|
2164
|
+
filter(token) {
|
|
2165
|
+
if (isTokenOnSameLine(prevToken, token)) {
|
|
2166
|
+
prevToken = token;
|
|
2167
|
+
return false;
|
|
2168
|
+
}
|
|
2169
|
+
return true;
|
|
2170
|
+
}
|
|
2171
|
+
}) || nextNode;
|
|
2172
|
+
const insertText = isTokenOnSameLine(prevToken, nextToken) ? `
|
|
2173
|
+
|
|
2174
|
+
` : `
|
|
2175
|
+
`;
|
|
2176
|
+
return fixer.insertTextAfter(prevToken, insertText);
|
|
2177
|
+
}
|
|
2178
|
+
});
|
|
2179
|
+
}
|
|
2180
|
+
var PaddingTypes = {
|
|
2181
|
+
any: { verify: verifyForAny },
|
|
2182
|
+
never: { verify: verifyForNever },
|
|
2183
|
+
always: { verify: verifyForAlways }
|
|
2184
|
+
};
|
|
2185
|
+
var MaybeMultilineStatementType = {
|
|
2186
|
+
"block-like": { test: isBlockLikeStatement },
|
|
2187
|
+
expression: { test: isExpression },
|
|
2188
|
+
return: newKeywordTester("ReturnStatement", "return"),
|
|
2189
|
+
export: newKeywordTester([
|
|
2190
|
+
"ExportAllDeclaration",
|
|
2191
|
+
"ExportDefaultDeclaration",
|
|
2192
|
+
"ExportNamedDeclaration"
|
|
2193
|
+
], "export"),
|
|
2194
|
+
var: newKeywordTester("VariableDeclaration", "var"),
|
|
2195
|
+
let: newKeywordTester("VariableDeclaration", "let"),
|
|
2196
|
+
const: newKeywordTester("VariableDeclaration", "const"),
|
|
2197
|
+
using: {
|
|
2198
|
+
test: (node) => node.type === "VariableDeclaration" && (node.kind === "using" || node.kind === "await using")
|
|
2199
|
+
},
|
|
2200
|
+
type: newKeywordTester("TSTypeAliasDeclaration", "type")
|
|
2201
|
+
};
|
|
2202
|
+
var StatementTypes = {
|
|
2203
|
+
"*": { test: () => true },
|
|
2204
|
+
exports: { test: isCJSExport },
|
|
2205
|
+
require: { test: isCJSRequire },
|
|
2206
|
+
directive: { test: isDirectivePrologue },
|
|
2207
|
+
iife: { test: isIIFEStatement },
|
|
2208
|
+
block: newNodeTypeTester("BlockStatement"),
|
|
2209
|
+
empty: newNodeTypeTester("EmptyStatement"),
|
|
2210
|
+
function: newNodeTypeTester("FunctionDeclaration"),
|
|
2211
|
+
"ts-method": newNodeTypeTester("TSMethodSignature"),
|
|
2212
|
+
break: newKeywordTester("BreakStatement", "break"),
|
|
2213
|
+
case: newKeywordTester("SwitchCase", "case"),
|
|
2214
|
+
class: newKeywordTester("ClassDeclaration", "class"),
|
|
2215
|
+
continue: newKeywordTester("ContinueStatement", "continue"),
|
|
2216
|
+
debugger: newKeywordTester("DebuggerStatement", "debugger"),
|
|
2217
|
+
default: newKeywordTester(["SwitchCase", "ExportDefaultDeclaration"], "default"),
|
|
2218
|
+
do: newKeywordTester("DoWhileStatement", "do"),
|
|
2219
|
+
for: newKeywordTester([
|
|
2220
|
+
"ForStatement",
|
|
2221
|
+
"ForInStatement",
|
|
2222
|
+
"ForOfStatement"
|
|
2223
|
+
], "for"),
|
|
2224
|
+
if: newKeywordTester("IfStatement", "if"),
|
|
2225
|
+
import: newKeywordTester("ImportDeclaration", "import"),
|
|
2226
|
+
switch: newKeywordTester("SwitchStatement", "switch"),
|
|
2227
|
+
throw: newKeywordTester("ThrowStatement", "throw"),
|
|
2228
|
+
try: newKeywordTester("TryStatement", "try"),
|
|
2229
|
+
while: newKeywordTester(["WhileStatement", "DoWhileStatement"], "while"),
|
|
2230
|
+
with: newKeywordTester("WithStatement", "with"),
|
|
2231
|
+
"cjs-export": {
|
|
2232
|
+
test: (node, sourceCode) => node.type === "ExpressionStatement" && node.expression.type === "AssignmentExpression" && CJS_EXPORT.test(sourceCode.getText(node.expression.left))
|
|
2233
|
+
},
|
|
2234
|
+
"cjs-import": {
|
|
2235
|
+
test: (node, sourceCode) => node.type === "VariableDeclaration" && node.declarations.length > 0 && node.declarations[0]?.init != null && CJS_IMPORT.test(sourceCode.getText(node.declarations[0].init))
|
|
2236
|
+
},
|
|
2237
|
+
enum: newKeywordTester("TSEnumDeclaration", "enum"),
|
|
2238
|
+
interface: newKeywordTester("TSInterfaceDeclaration", "interface"),
|
|
2239
|
+
"function-overload": newNodeTypeTester("TSDeclareFunction"),
|
|
2240
|
+
...Object.fromEntries(Object.entries(MaybeMultilineStatementType).flatMap(([key, value]) => [
|
|
2241
|
+
[key, value],
|
|
2242
|
+
[
|
|
2243
|
+
`singleline-${key}`,
|
|
2244
|
+
{
|
|
2245
|
+
...value,
|
|
2246
|
+
test: (node, sourceCode) => value.test(node, sourceCode) && isSingleLine(node)
|
|
2247
|
+
}
|
|
2248
|
+
],
|
|
2249
|
+
[
|
|
2250
|
+
`multiline-${key}`,
|
|
2251
|
+
{
|
|
2252
|
+
...value,
|
|
2253
|
+
test: (node, sourceCode) => value.test(node, sourceCode) && !isSingleLine(node)
|
|
2254
|
+
}
|
|
2255
|
+
]
|
|
2256
|
+
]))
|
|
2257
|
+
};
|
|
2258
|
+
function createPaddingLineRule(options) {
|
|
2259
|
+
return {
|
|
2260
|
+
meta: {
|
|
2261
|
+
type: "layout",
|
|
2262
|
+
docs: {
|
|
2263
|
+
description: "Require or disallow padding lines between statements"
|
|
2264
|
+
},
|
|
2265
|
+
fixable: "whitespace",
|
|
2266
|
+
hasSuggestions: false,
|
|
2267
|
+
schema: {
|
|
2268
|
+
$defs: {
|
|
2269
|
+
paddingType: {
|
|
2270
|
+
type: "string",
|
|
2271
|
+
enum: Object.keys(PaddingTypes)
|
|
2272
|
+
},
|
|
2273
|
+
statementType: {
|
|
2274
|
+
type: "string",
|
|
2275
|
+
enum: Object.keys(StatementTypes)
|
|
2276
|
+
},
|
|
2277
|
+
selectorOption: {
|
|
2278
|
+
type: "object",
|
|
2279
|
+
properties: {
|
|
2280
|
+
selector: {
|
|
2281
|
+
type: "string"
|
|
2282
|
+
},
|
|
2283
|
+
lineMode: {
|
|
2284
|
+
type: "string",
|
|
2285
|
+
enum: ["any", "singleline", "multiline"]
|
|
2286
|
+
}
|
|
2287
|
+
},
|
|
2288
|
+
required: ["selector"],
|
|
2289
|
+
additionalProperties: false
|
|
2290
|
+
},
|
|
2291
|
+
statementMatcher: {
|
|
2292
|
+
anyOf: [
|
|
2293
|
+
{ $ref: "#/$defs/statementType" },
|
|
2294
|
+
{ $ref: "#/$defs/selectorOption" }
|
|
2295
|
+
]
|
|
2296
|
+
},
|
|
2297
|
+
statementOption: {
|
|
2298
|
+
anyOf: [
|
|
2299
|
+
{ $ref: "#/$defs/statementMatcher" },
|
|
2300
|
+
{
|
|
2301
|
+
type: "array",
|
|
2302
|
+
items: { $ref: "#/$defs/statementMatcher" },
|
|
2303
|
+
minItems: 1,
|
|
2304
|
+
uniqueItems: true,
|
|
2305
|
+
additionalItems: false
|
|
2306
|
+
}
|
|
2307
|
+
]
|
|
2308
|
+
}
|
|
2309
|
+
},
|
|
2310
|
+
type: "array",
|
|
2311
|
+
additionalItems: false,
|
|
2312
|
+
items: {
|
|
2313
|
+
type: "object",
|
|
2314
|
+
properties: {
|
|
2315
|
+
blankLine: { $ref: "#/$defs/paddingType" },
|
|
2316
|
+
prev: { $ref: "#/$defs/statementOption" },
|
|
2317
|
+
next: { $ref: "#/$defs/statementOption" }
|
|
2318
|
+
},
|
|
2319
|
+
additionalProperties: false,
|
|
2320
|
+
required: ["blankLine", "prev", "next"]
|
|
2321
|
+
}
|
|
2322
|
+
},
|
|
2323
|
+
messages: {
|
|
2324
|
+
unexpectedBlankLine: "Unexpected blank line before this statement.",
|
|
2325
|
+
expectedBlankLine: "Expected blank line before this statement."
|
|
2326
|
+
}
|
|
2327
|
+
},
|
|
2328
|
+
create(context) {
|
|
2329
|
+
const sourceCode = context.sourceCode;
|
|
2330
|
+
const selectorMatchedNodes = new Map;
|
|
2331
|
+
const pendingPairs = [];
|
|
2332
|
+
function collectSelectorOption(option) {
|
|
2333
|
+
if (Array.isArray(option)) {
|
|
2334
|
+
for (const item of option)
|
|
2335
|
+
collectSelectorOption(item);
|
|
2336
|
+
return;
|
|
2337
|
+
}
|
|
2338
|
+
if (!isSelectorOption(option))
|
|
2339
|
+
return;
|
|
2340
|
+
selectorMatchedNodes.set(option.selector, new Set);
|
|
2341
|
+
}
|
|
2342
|
+
for (const configure of options) {
|
|
2343
|
+
collectSelectorOption(configure.prev);
|
|
2344
|
+
collectSelectorOption(configure.next);
|
|
2345
|
+
}
|
|
2346
|
+
let scopeInfo = null;
|
|
2347
|
+
function enterScope() {
|
|
2348
|
+
scopeInfo = {
|
|
2349
|
+
upper: scopeInfo,
|
|
2350
|
+
prevNode: null
|
|
2351
|
+
};
|
|
2352
|
+
}
|
|
2353
|
+
function exitScope() {
|
|
2354
|
+
if (scopeInfo)
|
|
2355
|
+
scopeInfo = scopeInfo.upper;
|
|
2356
|
+
}
|
|
2357
|
+
function match(node, type) {
|
|
2358
|
+
let innerStatementNode = node;
|
|
2359
|
+
while (innerStatementNode.type === "LabeledStatement")
|
|
2360
|
+
innerStatementNode = innerStatementNode.body;
|
|
2361
|
+
if (Array.isArray(type))
|
|
2362
|
+
return type.some(match.bind(null, innerStatementNode));
|
|
2363
|
+
if (isSelectorOption(type)) {
|
|
2364
|
+
const matchedNodes = selectorMatchedNodes.get(type.selector);
|
|
2365
|
+
if (!matchedNodes?.has(innerStatementNode))
|
|
2366
|
+
return false;
|
|
2367
|
+
const lineMode = type.lineMode;
|
|
2368
|
+
if (lineMode === "singleline")
|
|
2369
|
+
return isSingleLine(innerStatementNode);
|
|
2370
|
+
else if (lineMode === "multiline")
|
|
2371
|
+
return !isSingleLine(innerStatementNode);
|
|
2372
|
+
return true;
|
|
2373
|
+
} else {
|
|
2374
|
+
const statementType = StatementTypes[type];
|
|
2375
|
+
if (statementType === undefined)
|
|
2376
|
+
throw new Error(`Padding rule invariant: unsupported statement type ${type}`);
|
|
2377
|
+
return statementType.test(innerStatementNode, sourceCode);
|
|
2378
|
+
}
|
|
2379
|
+
}
|
|
2380
|
+
function getPaddingType(prevNode, nextNode) {
|
|
2381
|
+
for (let i = options.length - 1;i >= 0; --i) {
|
|
2382
|
+
const configure = options[i];
|
|
2383
|
+
if (configure === undefined)
|
|
2384
|
+
throw new Error("Padding rule invariant: configuration entry is missing");
|
|
2385
|
+
if (match(prevNode, configure.prev) && match(nextNode, configure.next)) {
|
|
2386
|
+
return PaddingTypes[configure.blankLine];
|
|
2387
|
+
}
|
|
2388
|
+
}
|
|
2389
|
+
return PaddingTypes.any;
|
|
2390
|
+
}
|
|
2391
|
+
function getPaddingLineSequences(prevNode, nextNode) {
|
|
2392
|
+
const pairs = [];
|
|
2393
|
+
let prevToken = getActualLastToken(prevNode, sourceCode);
|
|
2394
|
+
if (nextNode.loc.start.line - prevToken.loc.end.line >= 2) {
|
|
2395
|
+
do {
|
|
2396
|
+
const token = sourceCode.getTokenAfter(prevToken, {
|
|
2397
|
+
includeComments: true
|
|
2398
|
+
});
|
|
2399
|
+
if (token.loc.start.line - prevToken.loc.end.line >= 2)
|
|
2400
|
+
pairs.push([prevToken, token]);
|
|
2401
|
+
prevToken = token;
|
|
2402
|
+
} while (prevToken.range[0] < nextNode.range[0]);
|
|
2403
|
+
}
|
|
2404
|
+
return pairs;
|
|
2405
|
+
}
|
|
2406
|
+
function verify(node) {
|
|
2407
|
+
if (!node.parent || ![
|
|
2408
|
+
"BlockStatement",
|
|
2409
|
+
"Program",
|
|
2410
|
+
"StaticBlock",
|
|
2411
|
+
"SwitchCase",
|
|
2412
|
+
"SwitchStatement",
|
|
2413
|
+
"TSInterfaceBody",
|
|
2414
|
+
"TSModuleBlock",
|
|
2415
|
+
"TSTypeLiteral"
|
|
2416
|
+
].includes(node.parent.type)) {
|
|
2417
|
+
return;
|
|
2418
|
+
}
|
|
2419
|
+
const prevNode = scopeInfo.prevNode;
|
|
2420
|
+
if (prevNode)
|
|
2421
|
+
pendingPairs.push({ prevNode, nextNode: node });
|
|
2422
|
+
scopeInfo.prevNode = node;
|
|
2423
|
+
}
|
|
2424
|
+
function verifyPendingPairs() {
|
|
2425
|
+
for (const { prevNode, nextNode } of pendingPairs) {
|
|
2426
|
+
const type = getPaddingType(prevNode, nextNode);
|
|
2427
|
+
const paddingLines = getPaddingLineSequences(prevNode, nextNode);
|
|
2428
|
+
type.verify(context, prevNode, nextNode, paddingLines);
|
|
2429
|
+
}
|
|
2430
|
+
}
|
|
2431
|
+
function verifyThenEnterScope(node) {
|
|
2432
|
+
verify(node);
|
|
2433
|
+
enterScope();
|
|
2434
|
+
}
|
|
2435
|
+
const selectorMatchListeners = Object.fromEntries(Array.from(selectorMatchedNodes.keys(), (selector) => [
|
|
2436
|
+
selector,
|
|
2437
|
+
(node) => {
|
|
2438
|
+
selectorMatchedNodes.get(selector)?.add(node);
|
|
2439
|
+
}
|
|
2440
|
+
]));
|
|
2441
|
+
return {
|
|
2442
|
+
Program: enterScope,
|
|
2443
|
+
"Program:exit": () => {
|
|
2444
|
+
verifyPendingPairs();
|
|
2445
|
+
exitScope();
|
|
2446
|
+
},
|
|
2447
|
+
BlockStatement: enterScope,
|
|
2448
|
+
"BlockStatement:exit": exitScope,
|
|
2449
|
+
SwitchStatement: enterScope,
|
|
2450
|
+
"SwitchStatement:exit": exitScope,
|
|
2451
|
+
SwitchCase: verifyThenEnterScope,
|
|
2452
|
+
"SwitchCase:exit": exitScope,
|
|
2453
|
+
StaticBlock: enterScope,
|
|
2454
|
+
"StaticBlock:exit": exitScope,
|
|
2455
|
+
TSInterfaceBody: enterScope,
|
|
2456
|
+
"TSInterfaceBody:exit": exitScope,
|
|
2457
|
+
TSModuleBlock: enterScope,
|
|
2458
|
+
"TSModuleBlock:exit": exitScope,
|
|
2459
|
+
TSTypeLiteral: enterScope,
|
|
2460
|
+
"TSTypeLiteral:exit": exitScope,
|
|
2461
|
+
TSDeclareFunction: verifyThenEnterScope,
|
|
2462
|
+
"TSDeclareFunction:exit": exitScope,
|
|
2463
|
+
TSMethodSignature: verifyThenEnterScope,
|
|
2464
|
+
"TSMethodSignature:exit": exitScope,
|
|
2465
|
+
":statement": verify,
|
|
2466
|
+
...selectorMatchListeners
|
|
2467
|
+
};
|
|
2468
|
+
}
|
|
2469
|
+
};
|
|
2470
|
+
}
|
|
2471
|
+
var paddingRule = createPaddingLineRule([
|
|
2472
|
+
{ blankLine: "always", prev: "import", next: "*" },
|
|
2473
|
+
{ blankLine: "always", prev: "*", next: { selector: "Program > :not(ImportDeclaration)" } },
|
|
2474
|
+
{ blankLine: "always", prev: { selector: "Program > :not(ImportDeclaration)" }, next: "*" },
|
|
2475
|
+
{ blankLine: "always", prev: "*", next: ["function", "class", "interface", "type"] },
|
|
2476
|
+
{ blankLine: "always", prev: ["function", "class", "interface", "type"], next: "*" },
|
|
2477
|
+
{
|
|
2478
|
+
blankLine: "always",
|
|
2479
|
+
prev: "*",
|
|
2480
|
+
next: ["multiline-const", "multiline-let", "multiline-var", "multiline-using"]
|
|
2481
|
+
},
|
|
2482
|
+
{
|
|
2483
|
+
blankLine: "always",
|
|
2484
|
+
prev: ["multiline-const", "multiline-let", "multiline-var", "multiline-using"],
|
|
2485
|
+
next: "*"
|
|
2486
|
+
},
|
|
2487
|
+
{ blankLine: "always", prev: "*", next: ["return", "if", "switch", "try", "for", "while", "do"] },
|
|
2488
|
+
{ blankLine: "always", prev: "block-like", next: "*" },
|
|
2489
|
+
{ blankLine: "any", prev: "import", next: "import" },
|
|
2490
|
+
{
|
|
2491
|
+
blankLine: "any",
|
|
2492
|
+
prev: {
|
|
2493
|
+
selector: ':matches(TSDeclareFunction, ExportNamedDeclaration[declaration.type="TSDeclareFunction"])'
|
|
2494
|
+
},
|
|
2495
|
+
next: {
|
|
2496
|
+
selector: ':matches(TSDeclareFunction, FunctionDeclaration, ExportNamedDeclaration[declaration.type="TSDeclareFunction"], ExportNamedDeclaration[declaration.type="FunctionDeclaration"])'
|
|
2497
|
+
}
|
|
2498
|
+
}
|
|
2499
|
+
]);
|
|
2500
|
+
var requireReadableSpacingRule = {
|
|
2501
|
+
...paddingRule,
|
|
2502
|
+
meta: {
|
|
2503
|
+
...paddingRule.meta,
|
|
2504
|
+
docs: {
|
|
2505
|
+
description: "Require readable spacing between declarations and logical statement groups."
|
|
2506
|
+
},
|
|
2507
|
+
schema: []
|
|
2508
|
+
}
|
|
2509
|
+
};
|
|
1831
2510
|
var DEFAULT_SAFETY_MARKERS = ["SAFETY"];
|
|
1832
2511
|
var commentOwnerKinds = new Set([
|
|
1833
2512
|
"ExpressionStatement",
|
|
@@ -1921,6 +2600,8 @@ var requireSafetyCommentForTypeAssertionRule = defineRule({
|
|
|
1921
2600
|
var antiSlopPlugin = eslintCompatPlugin({
|
|
1922
2601
|
meta: { name: "anti-slop" },
|
|
1923
2602
|
rules: {
|
|
2603
|
+
"no-array-filter-map": noArrayFilterMapRule,
|
|
2604
|
+
"no-reduce-accumulator-copy": noReduceAccumulatorCopyRule,
|
|
1924
2605
|
"no-chained-type-assertions": noChainedTypeAssertionsRule,
|
|
1925
2606
|
"no-conditional-empty-object-spread": noConditionalEmptyObjectSpreadRule,
|
|
1926
2607
|
"no-known-value-widening": noKnownValueWideningRule,
|
|
@@ -1935,6 +2616,7 @@ var antiSlopPlugin = eslintCompatPlugin({
|
|
|
1935
2616
|
"no-unknown-returns": noUnknownReturnsRule,
|
|
1936
2617
|
"no-unknown-type-aliases": noUnknownTypeAliasesRule,
|
|
1937
2618
|
"no-widen-then-assert": noWidenThenAssertRule,
|
|
2619
|
+
"require-readable-spacing": requireReadableSpacingRule,
|
|
1938
2620
|
"require-safety-comment-for-type-assertion": requireSafetyCommentForTypeAssertionRule
|
|
1939
2621
|
}
|
|
1940
2622
|
});
|